狀態模式
本文主要內容
- 狀態模式簡介
- 狀態模式例項
- 總結
1、狀態模式簡介
當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類
狀態模式的一般使用場景:
- 一個物件的行為取決於它的狀態,並且必須在執行時根據它的狀態改變它的行為
- 程式碼中包含大量與狀態有關的條件語句,如有很多if else
從第2條來看,狀態模式與策略模式類似,但它和策略模式是不一樣的,狀態模式的所有狀態,肯定是有切換的,不同狀態不同的行為,遇到不同的環境狀態會變化。它的內含偏向於,不同狀態下不同的處理邏輯。而策略模式,偏向於同樣的功能不同的實現。

狀態模式UML圖
2、狀態模式例項
我們以電視遙控器為例。遙控器可以調臺,並且調節音量。但電視只有在開機的狀態下才能實現上述功能,關機的時候按鈕無效。那麼我們應該怎麼去抽象這個狀態類呢?
使用狀態模式時,非常重要的一點是分清楚哪裡是不同狀態下能做的操作?哪些是切換狀態的因素。遙控器這個例子中,開關機顯示是切換狀態的因素,調臺和調音量顯示是不同狀態下的操作。
當我們在定義狀態介面時,一定不能把導致狀態切換的因素也寫到狀態介面中,否則會很彆扭。這麼一分析,狀態介面可以這麼寫:
public interface TvState { public void nextChannel(); public void preChannel(); public void turnUp(); public void turnDown(); }
開機狀態實現:
public class PowerOnState implements TvState{ @Override public void nextChannel() { System.out.println("下一個頻道"); } @Override public void preChannel() { System.out.println("上一個頻道"); } @Override public void turnUp() { System.out.println("增大音量"); } @Override public void turnDown() { System.out.println("減小音量"); } }
關機狀態什麼都不能做,所以這些函式都是空函式:
public class PowerOffState implements TvState{ @Override public void nextChannel() { } @Override public void preChannel() { } @Override public void turnUp() { } @Override public void turnDown() { } }
定義一個開關機的介面:
public interface PowerController { public void powerOn(); public void powerOff(); }
遙控器:
public class TvController implements PowerController{ TvState mState; public void setState(TvState tvState){ mState = tvState; } @Override public void powerOn() { System.out.println("開機了"); setState(new PowerOnState()); } @Override public void powerOff() { System.out.println("關機了"); setState(new PowerOffState()); } public void nextChannel() { mState.nextChannel(); } public void preChannel() { mState.preChannel(); } public void turnUp() { mState.turnUp(); } public void turnDown() { mState.turnDown(); } public static void main(String[] args) { TvController controller = new TvController(); controller.powerOn(); controller.nextChannel(); controller.turnDown(); controller.powerOff(); controller.turnUp(); } }
3、總結
示例比較簡單,最重要是理解狀態模式。尤其是狀態模式介面的定義,為啥不把開關機這個方法也寫到狀態介面當中來呢?因為如果開關機也在狀態介面中,那怎麼來切換狀態呢?導致狀態切換的原因一定要放在外面。另外就是認真體會下狀態模式和策略模式之間的差異了。策略模式側面的是不同演算法,而狀態模式側重的是不同狀態。