本文來自:曹勝歡部落格專欄。轉載請註明出處:http://blog.csdn.net/csh624366188
狀態模式:允許對象在內部狀態改變時改變它的行為,對象看起來好像修改了它的類。看起來,狀態模式好像是神通廣大很厲害似的——居然能夠“修改自身的類”!下面讓我們一起來看一下他的厲害吧!
適用情境:
狀態模式主要解決的是當控制一個對象狀態裝換的條件運算式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判 斷邏輯簡單化。當一個對象行為取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式了。
要點:
1. 策略模式和狀態模式是雙胞胎,它們有相同的類圖,但是它們的意圖不同。策略模式是圍繞可以互換的演算法來成功建立業務的,然而狀態模式是通過改變對象內部的狀態來協助對象控制自己的行為.
2. Context將與狀態相關的操作委託給當前的Concrete State對象處理。
3. Context可將自身作為一個參數傳遞給處理該請求的狀態物件。這使得狀態物件在必要時可訪問Context。
4. Context或Concrete State類都可決定哪個狀態是另外哪一個的後繼者,以及是在何種條件下進行狀態轉換。也就是說可以在State中儲存對Concrete State的引用,在必要時設定具體的狀態,做到狀態的轉換。
5. 一般來講,當狀態轉換是固定的時候,狀態轉換就適合放在Context中。然而,當轉換是更動態時候,通常會放到具體的狀態類中進行。(具體狀態類持有Context的引用,實現狀態的轉換)
Context類:維護一個ConcreteState子類的一個執行個體,這個執行個體定義當前的狀態。
State類:抽象狀態類,定義一個 介面以封裝與Context的一個特定狀態相關的行為。
ConcreteStateA,ConcreteStateB類:具體狀態類,每一個子 類實現一個與Context的一個狀態相關的行為。
具體實現:
先定義介面UserState
1 public interface UserState { 2 public UserService userService = new UserService(); 3 // 狀態為0代表普通使用者,這些狀態主要用於持久化到資料 4 public final static int COMMON_STATUS = 0; 5 // 狀態為1代表待審核使用者 6 public final static int FOR_VERIFY_STATUS = 1; 7 // 狀態為2是代表vip使用者 8 public final static int VIP_STATUS = 2; 9 10 // 提交資訊 11 public void submit() throws Exception; 12 13 // 審核沒通過 14 public void rollback() throws Exception; 15 16 // 審核通過 17 public void pass() throws Exception; 18 19 public int getStatus();
代表各個狀態的類
未提交資訊的使用者NotSubmitUser.java
2 public class NotSubmitUser implements UserState { 3 public void pass() throws Exception { 4 throw new Exception("no support method"); 5 } 6 7 public void rollback() throws Exception { 8 throw new Exception("no support method"); 9 } 10 11 public void submit() throws Exception { 12 User user = userService.getUser(0); 13 user.setStauts(FOR_VERIFY_STATUS); 14 userService.update(user); 15 } 16 17 public int getStatus() { 18 return COMMON_STATUS; 19 } 20 }
待審核的使用者WaitForVerifyUser.java
Java代碼
22 public class WaitForVerifyUser implements UserState { 23 24 public void pass() throws Exception { 25 User user = userService.getUser(0); 26 user.setStauts(VIP_STATUS); 27 userService.update(user); 28 } 29 30 public void rollback() throws Exception { 31 User user = userService.getUser(0); 32 user.setStauts(COMMON_STATUS); 33 userService.update(user); 34 } 35 36 public void submit() throws Exception { 37 throw new Exception("no support method"); 38 } 39 40 public int getStatus() { 41 return VIP_STATUS; 42 } 43 }
審核通過的使用者,vip VipUser.java
45 public class VipUser implements UserState { 46 47 public void pass() throws Exception { 48 throw new Exception("no support method"); 49 } 50 51 public void rollback() throws Exception { 52 User user = userService.getUser(0); 53 user.setStauts(COMMON_STATUS); 54 userService.update(user); 55 } 56 57 public void submit() throws Exception { 58 throw new Exception("no support method"); 59 } 60 61 public int getStatus() { 62 return FOR_VERIFY_STATUS; 63 } 64 }
根據使用者的status的返回不同的UserState
66 public class UserStateFactory { 67 static List list = null; 68 static { 69 list = new ArrayList(); 70 list.add(new NotSubmitUser()); 71 list.add(new VipUser()); 72 list.add(new WaitForVerifyUser()); 73 74 } 75 76 public static UserState getUserState(int status) { 77 for (UserState state : list) { 78 if (state.getStatus() == status) 79 return state; 80 } 81 return null; 82 } 83 }
狀態模式操作是固定的,但是接受者類不相同。多態性的原則實際執行哪個方法不僅取決與方法簽名,還取決與操作的接受者類。
該例子只是state模式的一個情境的應用,比較具體。
狀態模式的優點:
1.非常好的擴充性---假設增加一個使用者組:當vip使用者的信用達到一定程度後,升級到永久的vip。這時只需另外添加一個狀態類,對原來的代碼並不需要做改動。
2.代碼結構清晰,不同出錯。即程式健壯--除UserStateFactory的getUserState(int status)外,其他方法的邏輯非常的簡單,都不包含局部變數。如果程式不需要持久化到資料庫,也不需要getUserState(int status),該方法是狀態模式內容之外的 。用狀態模式類的數量會大大的增加。
說明:該例子只是狀態模式的一個應用,並不是狀態模式,是屬於比較具體