java常用設計模式6——狀態模式
狀態模式介紹:
1、狀態模式中的行為是由狀態來決定的,不同的狀態下有不同的行為。
2、狀態模式和策略模式的結構幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的,不可替換的,策略模式的行為是彼此獨立,可相互替換的。
3、狀態模式把物件的行為包裝在不同的狀態物件裡,每一個狀態物件都有一個共同的抽象狀態基類。
4、狀態模式的意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變。
使用場景:
一個物件的行為取決於它的狀態,並且它必須在執行時根據狀態改變它的行為。
UML圖:
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();
輸出:
可以看到,在吃飽的狀態下呼叫firstState方法可以成功變身一級狀態,而在飢餓的狀態下無法成功變身。
所有的判斷沒有用到If/else,而是根據自身的狀態改變,呼叫不同的方法,將不同的狀態行為封裝到不同的類裡。
基本上程式碼的構造和策略模式是一樣的,只不過策略的改變需要Client控制完成,而狀態的改變是由Context或狀態自己。
以上就是狀態模式的簡單介紹啦(#^ . ^#)