編輯:關於Android編程
這篇博客我們來介紹一下狀態模式(State Pattern),也是行為型設計模式之一。狀態模式的行為是由狀態來決定的,不同的狀態下有不同的行為。狀態模式和策略模式的結構類圖幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的、不可替換的,策略模式的行為是彼此獨立、可相互替換的。狀態模式把對象的行為包裝在不同的狀態對象裡,每一個狀態對象都有一個共同的抽象狀態基類;而策略模式可以想象成是除了繼承之外的一種彈性替代方案,如果你使用繼承定義了一個類的行為,你將被這個行為困住,甚至要修改它都很難,有了策略模式,你可以通過組合不同的對象來改變行為。狀態模式的意圖是讓一個對象在其內部狀態發生改變的時候,其行為也隨之改變。
當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。
狀態模式的使用場景:
vcfJq6O6PC9wPg0KQ29udGV4dKO6u7e+s8Dgo6y2qNLlv827p7jQ0MvIpLXEvdO/2qOszqy7pNK7uPYgU3RhdGUg19PA4KOs1eK49sq1wP22qNLlwcu21M/ztcS1scew17TMrKO7U3RhdGWjurPpz/PXtMyswOC78tXf17TMrL3Tv9qjrLao0uXSu7j2u/LV39K71+m907/ao6yx7cq+uMPXtMysz8K1xNDQzqqju0NvbmNyZXRlU3RhdGVBoaJDb25jcmV0ZVN0YXRlQqO6vt/M5de0zKzA4KOsw7/Su7j2vt/M5bXE17TMrMDgyrXP1rPpz/O1xCBTdGF0ZSDW0Lao0uW1xL3Tv9qjrLTTtvi077W9srvNrNe0zKzPwrXEsrvNrNDQzqqho6GhoaG+3bTLztLDx7/J0tTQtLP217TMrMSjyr21xM2o08O0+sLro7o8YnIgLz4NCte0zKy907/a0tS8sM/gudjX08Dgo7o8YnIgLz4NCjxzdHJvbmc+U3RhdGUuY2xhc3M8L3N0cm9uZz4NCjxwPiZuYnNwOzwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> public interface State { void doSomething(); }
ConcreteStateA.class、ConcreteStateB.class、NullState.class
public class ConcreteStateA implements State { @Override public void doSomething() { System.out.print("this is ConcreteStateA's function\n"); } }
public class ConcreteStateB implements State{ @Override public void doSomething() { System.out.print("this is ConcreteStateB's function\n"); } }
public class NullState implements State{ @Override public void doSomething() { //do nothing } }
Context類以及測試代碼:
Context.class
public class Context { private State state = new NullState(); void setState(State state) { this.state = state; } void doSomething() { state.doSomething(); } public static void main(String[] args) { Context context = new Context(); context.setState(new ConcreteStateA()); context.doSomething(); context.setState(new ConcreteStateB()); context.doSomething(); } }
最後結果:
this is ConcreteStateA's function this is ConcreteStateB's function
在 Android 源碼中也有很多狀態模式的例子,MediaPlayer 和 WifiStateEngine 等,這裡我們來簡單看看 MediaPlayer 的狀態機:
橢圓代表 MediaPlayer 對象可能駐留的狀態。弧線表示驅動 MediaPlayer 在各個狀態之間遷移的播放控制操作。這裡有兩種類型的弧線。由一個箭頭開始的弧代表同步的方法調用,而以雙箭頭開頭的代表的弧線代表異步方法調用。MediaPlayer在這我就不詳細介紹了,網上資料很多,感興趣的可以去查閱一下。
這裡再介紹一下狀態機,又稱為有限狀態自動機 (FSM:Finite State Machine),是表示有限多個狀態以及在這些狀態之間轉移和動作的數學模型。狀態存儲關於過去的信息,它反映從系統開始到現在時刻輸入的變化;轉移指示狀態變更,用必須滿足來確使轉移發生的條件來描述它;動作是在給定時刻要進行的活動描述,詳細的看看這篇博客:有限狀態機(FSM)的Java 演示 。
實際 Android 開發過程中,我們一般會去根據實際情況去先構造一個狀態圖,定義每個狀態和每個狀態之間切換的事件,類似於上圖的 MediaPlayer,然後將該信息錄入進入狀態機,當目前的狀態接收到一個非法的跳轉事件時,可以拋出異常,這樣就能保證一切按照預先設定好的方向進行。
我們這裡仍然以 wiki 上的 demo 為例,來實現一堆字符串的一個大小寫間隔打印:
Statelike.class
interface Statelike { void writeName(StateContext context, String name); }
StateLowerCase.class 和 StateMultipleUpperCase.class
class StateLowerCase implements Statelike { @Override public void writeName(final StateContext context, final String name) { System.out.println(name.toLowerCase()); context.setState(new StateMultipleUpperCase()); } }
class StateMultipleUpperCase implements Statelike { /** Counter local to this state */ private int count = 0; @Override public void writeName(final StateContext context, final String name) { System.out.println(name.toUpperCase()); /* Change state after StateMultipleUpperCase's writeName() gets invoked twice */ if(++count > 1) { context.setState(new StateLowerCase()); } } }
StateContext.class
class StateContext { private Statelike myState; StateContext() { setState(new StateLowerCase()); } /** * Setter method for the state. * Normally only called by classes implementing the State interface. * @param newState the new state of this context */ void setState(final Statelike newState) { myState = newState; } public void writeName(final String name) { myState.writeName(this, name); } public static void main(String[] args) { final StateContext sc = new StateContext(); sc.writeName("Monday"); sc.writeName("Tuesday"); sc.writeName("Wednesday"); sc.writeName("Thursday"); sc.writeName("Friday"); sc.writeName("Saturday"); sc.writeName("Sunday"); } }
最後結果:
monday TUESDAY WEDNESDAY thursday FRIDAY SATURDAY sunday
例子也很簡單,一目了然。
狀態模式的關鍵點在於不同的狀態下對於統一行為有不同的響應,這其實就是一個將 if-else 用多態來實現的一個具體實例。在 if-else 或者 switch-case 形勢下根據不同的狀態進行判斷,如果是狀態 A 那麼執行方法 A,狀態 B 執行方法 B,但這種實現使得邏輯耦合在一起,易於出錯不易維護,通過狀態模式能夠很好的消除這類“丑陋”的邏輯處理,當然並不是任何出現 if-else 的地方都應該通過狀態模式重構,模式的運用一定要考慮所處的情景以及你要解決的問題,只有符合特定的場景才建議使用對應的模式。和程序狀態機(PSM)不同,狀態模式用類代表狀態,狀態的轉換可以由 State 類或者 Context 類控制。
優點:
https://github.com/zhaozepeng/Design-Patterns/tree/master/StatePattern
Android App 內存洩露之Handler Handler也是造成內存洩露的一個重要的源頭,主要Handler屬於TLS(Thread Local Storage
android大家都有很多需要用戶上傳頭像的需求,有的是選方形,有的是圓角矩形,有的是圓形。首先我們要做一個處理圖片的自定義控件,把傳入的圖片,經過用戶選擇區域,處理成一
本文實例講述了Android動畫之補間動畫。分享給大家供大家參考,具體如下:前面講了《Android動畫之逐幀動畫(Frame Animation)》,今天就來詳細講解一
單Activity多Fragment實現底部導航器最近由於Android基礎知識講解需要,采用單Activity多Fragment實現類似QQ底部導航器示例,這種開發模式