遇到這樣的場景時,如: 紅綠燈狀態不同,行人的行為不同。網上購物時,訂單有不同的狀態。
電梯的執行狀態,維修,自動關門,開門,向上,向下等這些不同的狀態對應不同的行為時可以將狀態統一封裝
採用狀態模式來避免程式碼業務的耦合度過高。
用一句話來描述,狀態模式把所研究的物件的行為包裝在不同物件裡,每一個狀態物件都屬於一個抽象狀態
的子類,狀態模式的意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變。
組成:
環境類(Context): 定義客戶端需要的介面,並且負責具體狀態的切換。
抽象狀態類(State): 介面或抽象類,負責物件狀態定義,並且封裝環境角色以實現狀態切換。
具體狀態類(ConcreteState): 具體狀態主要有兩個職責:一是處理本狀態下的事情,二是從本狀態如何過渡到其他狀態。
例子:
模擬一個使用者系統登入,使用者的狀態有,logout,login,當使用者通過賬戶和密碼驗證後狀態為login, 當使用者退出時狀態為logout.
使用抽象狀態類限定了所有的表示不同行為的狀態,它的子類實現了由狀態決定的行為。
/** * 抽象狀態類 */ public interface State { void handle(); }
子類實現
public class UserLoginState implements State { @Override public void handle() { System.out.println("使用者通過密碼驗證狀態login"); } }
public class UserLogOutState implements State { @Override public void handle() { System.out.println("使用者通過密碼驗證狀態logOut"); } }
環境類持有一個狀態物件,來表示目前的狀態,接受所有狀態相關請求,並委派給具體的狀態物件處理
public class Context { //持有狀態物件 private State state; public void setState(State s){ System.out.println("修改狀態"); state = s; state.handle(); } }
public class Client { public static void main(String[] args) { Context ctx = new Context(); ctx.setState(new UserLoginState()); ctx.setState(new UserLogOutState()); } }
修改狀態 使用者通過密碼驗證狀態login 修改狀態 使用者通過密碼驗證狀態logOut Process finished with exit code 0
狀態模式達到的效果:
由於對系統所有的狀態抽象一個子類,當系統變化時,只需要改變所選的子類。同樣如果要新增狀態,也只需要增加新的子類。
由於沒一個狀態都被包裝到類裡,在程式碼業務處理時省去了大量的if..else判斷。
使用場景:
1.當一個物件的行為依賴它所處的狀態,也就是物件的行為隨狀態改變而改變。
2.當某個方法中存在大量的條件語句,可以考慮把這些條件語句抽象到狀態類中單獨維護。