一、定義
當一個對象内在狀态改變時允許其改變行為,這個對象看起來像改變了其類,狀态模式的核心是封裝,狀态的變更引起行為的變更,從外面看起來就像這個對象對應的類發生了改變一樣。
二、代碼示範
2.1 通用類圖
2.2 角色說明
-
State–抽象狀态角色
接口或抽象類,負責對象狀态定義,并且封裝環境角色以實作狀态切換。
-
ConcreteSate–具體狀态角色
每一個具體狀态必須要完成兩個職責:本狀态行為管理及趨向狀态處理,通俗的說就是本狀态要做的事情, 及如何過渡到其它狀态。
-
Context–環境角色
定義用戶端需要的接口,并且負責到狀态的切換。
狀态模式相對比較複雜,它提供了一種對物質運動的一個觀察視角,通過狀态變更促使行為的變化,這類似水的狀态變更一樣。 一碗水初始狀态是液體,通過加熱轉換為氣态,狀态的改變引起了體積變大。這就是蒸汽機的原理。
2.3 抽象狀态角色
抽象狀态角色,聲明一個環境角色, 提供給各狀态類自行通路,并且提供了各個狀态的抽象行為。
package com.design.state.pattern;
/**
* @description TODO
* @date: 2019/9/21 23:09
* @version: v 0.1
*/
public abstract class State {
//定義一個環境角色,提供子類通路
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//行為1
public abstract void handle1();
//行為2
public abstract void handle2();
}
2.4 具體狀态角色
每一個具體狀态必須要完成兩個職責:本狀态行為管理及趨向狀态處理,通俗的說就是本狀态要做的事情, 及如何過渡到其它狀态。
package com.design.state.pattern;
/**
* @description TODO
* @date: 2019/9/21 23:13
* @version: v 0.1
*/
public class ConcreteState1 extends State {
@Override
public void handle1() {
System.out.println("ConcreteState1.handle1 TODO");
//本狀态必須處理的邏輯
}
@Override
public void handle2() {
//設定目前狀态是state2
super.context.setCurrentState(Context.STATE2);
//過渡到state2狀态,有context實作
super.context.handle2();
}
}
package com.design.state.pattern;
/**
* @description TODO
* @date: 2019/9/21 23:13
* @version: v 0.1
*/
public class ConcreteState2 extends State {
@Override
public void handle2() {
System.out.println("ConcreteState1.handle2 TODO");
//本狀态必須處理的邏輯
}
@Override
public void handle1() {
//設定目前狀态是state2
super.context.setCurrentState(Context.STATE1);
//過渡到state2狀态,有context實作
super.context.handle1();
}
}
2.5 環境角色
package com.design.state.pattern;
/**
* @description TODO
* @date: 2019/9/21 23:17
* @version: v 0.1
*/
public class Context {
//定義狀态
public final static State STATE1 = new ConcreteState1();
public final static State STATE2 = new ConcreteState2();
//目前狀态
private State CurrentState;
//擷取目前狀态
public State getCurrentState() {
return CurrentState;
}
//設定目前狀态
public void setCurrentState(State _currentState) {
this.CurrentState = _currentState;
//切換狀态
this.CurrentState.setContext(this);
}
//行為委托
public void handle1() {
this.CurrentState.handle1();
}
//行為委托
public void handle2() {
this.CurrentState.handle2();
}
}
環境角色有兩個不成文的限制:
1)把狀态對象聲明為常量,有幾個狀态對象就聲明幾個靜态常量。
2)環境角色具有狀态抽象角色定義的所有行為,具體執行使用委托方式。
2.6 驗證場景類
package com.design.state.pattern;
/**
* @description TODO
* @date: 2019/9/21 23:09
* @version: v 0.1
*/
public abstract class State {
//定義一個環境角色,提供子類通路
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//行為1
public abstract void handle1();
//行為2
public abstract void handle2();
}
2.7 運作結果
ConcreteState1.handle1 TODO
ConcreteState2.handle2 TODO
三、優點
3.1 結構清晰
避免過多使用 switch…case或if…else 語句,避免了程式的複雜性,提高了可維護性。
3.2 遵循設計原則
提現了開閉原則和單一職責原則,每個狀态都是一個子類。
3.3 封閉性好
狀态變更是放在類的内部實作的, 外部調用不知道内部狀态變更邏輯。
四、缺點
可能會出現,子類太多導緻,類膨脹。
五、應用場景
- 行為随狀态改變而改變的場景。
- 條件、分支判斷的替代者,在程式中大量使用switch、if導緻邏輯混亂,使用狀态模式時,可以通過擴充子類實作條件的判斷處理。
六、注意事項
使用對象的狀态最好不要超過5個。