標籤:
第八章、狀態模式1.定義
狀態模式中的行為是由狀態來決定,不同的狀態下有不同的行為。當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。
2.使用情境
1.一個對象的行為取決於它的狀態,並且它必須在運行時根據狀態改變它的行為。
2.代碼中包含大量與對象狀態有關的條件陳述式,例如,一個操作中含有大量的多分支語句,且這些分支依賴於該對象的狀態。
3.簡單實現
實現效果:首先將電視的狀態分為開機與關機狀態,開機時可以通過遙控器實現頻道切換和調節音量,但是關機時,這些操作都會失效。
首先是普通的實現方法:
public class TVController { //開機狀態 private final static int POWER_ON = 1; //關機狀態 private final static int POWER_OFF = 2; //預設狀態 private int mState = POWER_OFF; public void powerOn(){ if(mState ==POWER_OFF){ System.out.println("電視開機了"); } mState = POWER_ON; } public void powerOff(){ if(mState ==POWER_ON){ System.out.println("電視關機了"); } mState = POWER_OFF; } public void nextChannel(){ if(mState ==POWER_ON){ System.out.println("下一頻道"); }else{ System.out.println("沒有開機"); } } public void prevChannel(){ if(mState ==POWER_ON){ System.out.println("上一頻道"); }else{ System.out.println("沒有開機"); } } public void turnUp(){ if(mState ==POWER_ON){ System.out.println("調高音量"); }else{ System.out.println("沒有開機"); } } public void turnDown(){ if(mState ==POWER_ON){ System.out.println("調低音量"); }else{ System.out.println("沒有開機"); } }}
可以看到,每次執行通過判斷目前狀態來進行操作,部分的代碼重複,假設狀態和功能增加,就會越來越難以維護。這時可以使用狀態模式,如下:
電視的操作
/** * 電視狀態介面,定義了電視的操作函數 * * */public interface TVState { public void nextChannel(); public void prevChannel(); public void turnUp(); public void turnDown();}
關機狀態
/** * * 關機狀態,操作無結果 * * */public class PowerOffState implements TVState{ @Override public void nextChannel() { } @Override public void prevChannel() { } @Override public void turnUp() { } @Override public void turnDown() { }}
開機狀態
/** * * 開機狀態,操作有效 * * */public class PowerOnState implements TVState{ @Override public void nextChannel() { System.out.println("下一頻道"); } @Override public void prevChannel() { System.out.println("上一頻道"); } @Override public void turnUp() { System.out.println("調高音量"); } @Override public void turnDown() { System.out.println("調低音量"); }}
電源操作介面
/** * 電源操作介面 * * */public interface PowerController { public void powerOn(); public void powerOff();}
電視遙控器
/** * 電視遙控器 * * */public class TVController implements PowerController{ TVState mTVState; public void setTVState(TVState mTVState){ this.mTVState = mTVState; } @Override public void powerOn() { setTVState(new PowerOnState()); System.out.println("開機了"); } @Override public void powerOff() { setTVState(new PowerOffState()); System.out.println("關機了"); } public void nextChannel(){ mTVState.nextChannel(); } public void prevChannel(){ mTVState.prevChannel(); } public void turnUp(){ mTVState.turnUp(); } public void turnDown(){ mTVState.turnDown(); }}
調用:
public class Client { public static void main(String[] args) { TVController tvController = new TVController(); //設定開機狀態 tvController.powerOn(); //下一頻道 tvController.nextChannel(); //調高音量 tvController.turnUp(); //關機 tvController.powerOff(); //調低音量,此時不會生效 tvController.turnDown(); }}
結果
開機了下一頻道調高音量關機了
可以看出,狀態模式將這些行為封裝到狀態類中,在進行操作時將這些功能轉寄給狀態物件,不同的狀態有不同的實現,去除了重複了if-else語句,這正是狀態模式的精髓所在。
4.與策略模式的區別
狀態模式與策略模式的結構幾乎是一樣的,就像是孿生兄弟。但是他們的目地、本質不一樣。狀態模式的行為是平行的、不可替換的,策略模式的行為是彼此獨立的、可相互替換的。狀態模式,通常是自我控制狀態的改變。而策略模式,是由外部指定使用什麼樣的策略。
5.Android實戰中的使用
1.登入系統,根據使用者是否登入,判斷事件的處理方式。
2.Wi-Fi管理,在不同的狀態下,WiFi的掃描請求處理不一。
6.總結1.優點
將所有與一個特定的狀態相關的行為都放入一個狀態物件中,它提供了一個更好的方法來組織與特定狀態相關的代碼,將繁瑣的狀態判斷轉換成結構清晰的狀態類族,在避免代碼膨脹的同時也保證了可擴充性與可維護性。
2.缺點
狀態模式的使用必然會增加系統類別和對象的個數。
《Android源碼設計模式解析與實戰》讀書筆記(八)