狀態模式包含以下幾個角色:java
● Context(環境類):環境類又稱爲上下文類,它是擁有多種狀態的對象。因爲環境類的狀態存在多樣性且在不一樣狀態下對象的行爲有所不一樣,所以將狀態獨立出去造成單獨的狀態類。在環境類中維護一個抽象狀態類State的實例,這個實例定義當前狀態,在具體實現時,它是一個State子類的對象。 ● State(抽象狀態類):它用於定義一個接口以封裝與環境類的一個特定狀態相關的行爲,在抽象狀態類中聲明瞭各類不一樣狀態對應的方法,而在其子類中實現類這些方法,因爲不一樣狀態下對象的行爲可能不一樣,所以在不一樣子類中方法的實現可能存在不一樣,相同的方法能夠寫在抽象狀態類中。 ● ConcreteState(具體狀態類):它是抽象狀態類的子類,每個子類實現一個與環境類的一個狀態相關的行爲,每個具體狀態類對應環境的一個具體狀態,不一樣的具體狀態類其行爲有所不一樣
一、主要優勢測試
(1) 封裝了狀態的轉換規則,在狀態模式中能夠將狀態的轉換代碼封裝在環境類或者具體狀態類中,能夠對狀態轉換代碼進行集中管理,而不是分散在一個個業務方法中。 (2) 將全部與某個狀態有關的行爲放到一個類中,只須要注入一個不一樣的狀態對象便可使環境對象擁有不一樣的行爲。 (3) 容許狀態轉換邏輯與狀態對象合成一體,而不是提供一個巨大的條件語句塊,狀態模式可讓咱們避免使用龐大的條件語句來將業務方法和狀態轉換代碼交織在一塊兒。 (4) 可讓多個環境對象共享一個狀態對象,從而減小系統中對象的個數
二、主要缺點this
(1) 狀態模式的使用必然會增長系統中類和對象的個數,致使系統運行開銷增大。 (2) 狀態模式的結構與實現都較爲複雜,若是使用不當將致使程序結構和代碼的混亂,增長系統設計的難度。 (3) 狀態模式對「開閉原則」的支持並不太好,增長新的狀態類須要修改那些負責狀態轉換的源代碼,不然沒法轉換到新增狀態;並且修改某個狀態類的行爲也需修改對應類的源代碼。
三、適用場景設計
(1) 對象的行爲依賴於它的狀態(如某些屬性值),狀態的改變將致使行爲的變化。 (2) 在代碼中包含大量與對象狀態有關的條件語句,這些條件語句的出現,會致使代碼的可維護性和靈活性變差,不能方便地增長和刪除狀態,而且致使客戶類與類庫之間的耦合加強。
王者榮耀中的狀態模式(李信光、暗形態):code
/** * 2018/12/6 * 狀態模式的切換類 * * @author machuanpeng */ public class LiXinContext { private int stateInt; private State state; public LiXinContext() { this.stateInt = 0; this.state = new OriginalState(); } public State getState() { return state; } public void setState(State state) { this.state = state; } public int getStateInt() { return stateInt; } public void setStateInt(int stateInt) { this.stateInt = stateInt; } public void bigOperation() { // 釋放大招 state.bigOperation(this); } }
/** * 2018/12/6 * State * * @author machuanpeng */ public abstract class State { public void bigOperation(LiXinContext context) }
/** * 2018/12/6 * 初始形態 * * @author machuanpeng */ public class OriginalState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==0){ System.out.println("原始形態沒有大招!"); }else{ context.setState(new LightState()); context.bigOperation(); } } }
/** * 2018/12/6 * 光形態 * * @author machuanpeng */ public class LightState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==1){ System.out.println("光形態蓄力,三道光!"); }else if(context.getStateInt()<1){ context.setState(new OriginalState()); context.bigOperation(); }else if(context.getStateInt()>1){ context.setState(new DarkState()); context.bigOperation(); } } }
/** * 2018/12/6 * 暗形態 * * @author machuanpeng */ public class DarkState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==2){ System.out.println("暗形態拍地板,彈起對方!"); }else{ context.setState(new LightState()); context.bigOperation(); } } }
測試:對象
public class Client { public static void main(String args[]) { LiXinContext context = new LiXinContext(); context.bigOperation(); context.setStateInt(1); context.bigOperation(); } }