在需求開發的過程中,經常會遇到根據不同的情況作出不同的處理。最直接的就是if...else...。
當場景特別復雜時,判斷if就有些力不從心了。加一個場景需要修改大量的代碼,這不是一個很好的做法。程序的擴展性特別薄弱。
舉個栗子:
當我們給朋友手機打電話的時候,朋友的手機就可能出現幾種情況:用戶開機,用戶關機,用戶欠費停機,用戶銷戶等。不同的場景產生不同的結果。
狀態模式
狀態模式就是用來解決大量不同場景不同行為的模式。
狀態模式:允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。
狀態模式包含的角色
Context:環境類
State:抽象狀態類
ConcreteState:具體狀態類
模式結構
示例
日常生活中,我們遇到的最多的帶有狀態的對象應該就是電梯了,電梯有開門,關門,運行,停止狀態。
public interface ILift {
// 電梯門開狀態
public void open();
// 電梯關門狀態
public void close();
// 電梯移動狀態
public void run();
// 電梯停止狀態
public void stop();
}
電梯的接口有了,我們可以來看下實現類:
public class Lift implements ILift {
public void open() {
System.out.println("lift is opening");
}
public void close() {
System.out.println("lift is closed");
}
public void run() {
System.out.println("lift run up or down");
}
public void stop() {
System.out.println("lift stopped");
}
}
下面就是電梯類怎么調用的問題?我們知道狀態之間是有一定的前提條件的,也就是說狀態不能隨意轉化。
如果電梯處於open狀態,那它下一個必然是close關門狀態,而不能是run狀態;當電梯是close狀態,可以是run,open,stop(沒按樓層)狀態。如下:
Y:代表可以進行狀態轉化
N:代表不能進行轉化
O:代表自己對自己,忽略
open
close
run
stop
open
O
Y
N
N
close
Y
O
Y
N
run
N
N
O
Y
stop
Y
N
Y
O
由於我們要進行電梯的狀態轉換,因此需要定義出電梯的狀態:
public interface ILift {
public final static int OPEN_STATE = 1;
public final static int CLOSE_STATE = 2;
public final static int RUN_STATE = 3;
public final static int STOP_STATE = 4;
// 設置電梯狀態
public void setState(int state);
// 電梯門開狀態
public void open();
// 電梯關門狀態
public void close();
// 電梯移動狀態
public void run();
// 電梯停止狀態
public void stop();
}
在這邊我們把電梯看成了一個對象,里面有狀態和狀態相應的動作,可以想象后面我們的調用代碼基本就是依次調用Lift類的各個函數。
缺點:如果電梯還有其他狀態(比如通電,斷電狀態),則Lift類要修改,不符合開閉原則。
根據狀態模式,我們思考把狀態看做一個對象,更細粒度的切分電梯這個類,把電梯的每個狀態當成一個類,我們來試驗下:
public abstract class LiftState {
//狀態轉換
private StageChange stageChange;
// 電梯門開狀態
public abstract void open();
// 電梯關門狀態
public abstract void close();
// 電梯移動狀態
public abstract void run();
// 電梯停止狀態
public abstract void stop();
}
StageChange是狀態轉換類,用來進行狀態的裝換。每個狀態都有自身的行為,比如Open狀態有一系列自己的行為:
public class LiftOpenState extends LiftState {
public void open() {
System.out.println("電梯門已經開啟");
}
public void close() {
super.stageChange.setLiftState(StageChange.closeState);
super.stageChange.getLiftState().close();
System.out.println("電梯關門");
}
public void run() {
}
public void stop() {
}
}
狀態模式通過一系列狀態自身的流轉來達到不同的場景執行不同的動作。
優點
結構清晰
封裝性好
狀態機
作者:ericsonyc
鏈接:https://www.jianshu.com/p/fc0a6396282c
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。