在需求開發的過程中,經常會遇到根據不同的情況作出不同的處理。最直接的就是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
O
Y
N
由于我們要進行電梯的狀态轉換,是以需要定義出電梯的狀态:
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);
在這邊我們把電梯看成了一個對象,裡面有狀态和狀态相應的動作,可以想象後面我們的調用代碼基本就是依次調用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 {
System.out.println("電梯門已經開啟");
super.stageChange.setLiftState(StageChange.closeState);
super.stageChange.getLiftState().close();
System.out.println("電梯關門");
狀态模式通過一系列狀态自身的流轉來達到不同的場景執行不同的動作。
優點
結構清晰
封裝性好
狀态機