1. 程式人生 > >java常用設計模式6——狀態模式

java常用設計模式6——狀態模式

狀態模式介紹:
1、狀態模式中的行為是由狀態來決定的,不同的狀態下有不同的行為。
2、狀態模式和策略模式的結構幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的,不可替換的,策略模式的行為是彼此獨立,可相互替換的。
3、狀態模式把物件的行為包裝在不同的狀態物件裡,每一個狀態物件都有一個共同的抽象狀態基類。
4、狀態模式的意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變。

使用場景:
一個物件的行為取決於它的狀態,並且它必須在執行時根據狀態改變它的行為。

UML圖:
state

Context : 環境類,定義客戶感興趣的介面,維護一個State子類的例項,這個例項定義了物件的當前狀態。
State : 抽象狀態類或者狀態介面,定義一個或者一組介面,表示該狀態下的行為。
ConcreteStateA、ConcreteStateA : 具體狀態類,每一個具體的狀態類實現抽象State的介面,從而達到不同狀態下的不同行為。

程式碼示例:
比如草帽路飛,吃飽的時候可以進行攻擊,飢餓狀態不能攻擊。
通常的程式碼是這樣的:

public class CommonFightController implements FightState {

    //吃飽狀態
    private final static int POWER_ON = 1;
    //飢餓狀態
    private final static int POWER_OFF = 2;
    private int mState = POWER_OFF;

    public void powerOn() {
        mState = POWER_ON;
} public void powerOff() { mState = POWER_OFF; } @Override public void firstState() { if (mState == POWER_ON) { Log.i("LHD", "一級狀態"); } else { Log.i("LHD", "肉、肉、肉"); } } @Override public void secondState() {
if (mState == POWER_ON) { Log.i("LHD", "二級狀態"); } else { Log.i("LHD", "肉、肉、肉"); } } }

可以看到,mState 方法記錄了路飛當前的身體狀態,然後在每個方法裡使用if/else根據當前狀態呼叫不同的方法。
這還是隻有兩個方法的情況,如果有多個方法,每個方法裡都要if/else判斷的話就會讓程式碼變得越來越臃腫,難以維護。

狀態模式就是為了這種情況出現的。
我們使用狀態模式改造一下

1、戰鬥狀態介面,定義戰鬥的狀態
public interface FightState {
    public void firstState();

    public void secondState();
}
2、吃飽狀態可以戰鬥啦
public class PowerOnState implements FightState {
    @Override
    public void firstState() {
        Log.i("LHD", "變身一級狀態");
    }

    @Override
    public void secondState() {
        Log.i("LHD", "變身二級狀態");
    }
}
3、飢餓狀態不能戰鬥
public class PowerOffState implements FightState {
    @Override
    public void firstState() {
        Log.i("LHD", "肉、肉、肉");
    }

    @Override
    public void secondState() {
        Log.i("LHD", "肉、肉、肉");
    }

}
4、狀態控制介面
public interface PowerController {
    public void powerOn();

    public void powerOff();
}
5、真實的狀態控制類
public class FightController implements PowerController, FightState {

    FightState fightState;

    public void setFightState(FightState fightState) {
        this.fightState = fightState;
    }

    @Override
    public void powerOn() {
        Log.i("LHD", "吃飽啦!");
        setFightState(new PowerOnState());
    }

    @Override
    public void powerOff() {
        Log.i("LHD", "我餓啦!");
        setFightState(new PowerOffState());
    }


    @Override
    public void firstState() {
        fightState.firstState();
    }

    @Override
    public void secondState() {
        fightState.secondState();
    }

}
使用方式:
       FightController tvController = new FightController();
       //吃飽
       tvController.powerOn();
       //戰鬥
       tvController.firstState();

       //飢餓
       tvController.powerOff();
       //沒法戰鬥
       tvController.firstState();
輸出:

state

可以看到,在吃飽的狀態下呼叫firstState方法可以成功變身一級狀態,而在飢餓的狀態下無法成功變身。
所有的判斷沒有用到If/else,而是根據自身的狀態改變,呼叫不同的方法,將不同的狀態行為封裝到不同的類裡。

基本上程式碼的構造和策略模式是一樣的,只不過策略的改變需要Client控制完成,而狀態的改變是由Context或狀態自己。

以上就是狀態模式的簡單介紹啦(#^ . ^#)