狀态模式又是一個比較難的設計模式
定義如下:
當一個對象内在狀态改變時允許其改變行為,這個對象看起來像改變了其類。
個人了解:通俗的講,狀态模式就是狀态的改變引起了行為的改變,但是,我們隻能看到行為的改變,看不到狀态的改變。
通用類圖:
角色介紹:
● State——抽象狀态角色
接口或抽象類,負責對象狀态定義,并且封裝環境角色以實作狀态切換。
● Concrete State——具體狀态角色
每一個具體狀态必須完成兩個職責:本狀态的行為管理以及趨向狀态處理,通俗地說,就是本狀态下要做的事情,以及本狀态如何過渡到其他狀态。
● Context——環境角色
定義用戶端需要的接口,并且負責具體狀态的切換。
舉個例子:
狀态模式提供了一種對物質運動的另一個觀察視角,通過狀态變更促使行為的變化,就類似水的狀态變更一樣,一碗水的初始狀态是液态,通過加熱轉變為氣态,狀态的改變同時也引起體積的擴大,然後就産生了一個新的行為:鳴笛或頂起壺蓋。
通用源代碼:
//抽象狀态角色
public abstract class State {
//定義一個環境角色,提供子類通路
protected Context context;
//設定環境角色
public void set Context(Context _context){
this.context = _context;
}
//行為1
public abstract void handle1();
//行為2
public abstract void handle2();
}
抽象狀态中聲明一個環境角色,提供各個狀态類自行通路,并且提供所有狀态的抽象行為,由各個實作類實作。
//具體狀态角色
public class Concrete State1 extends State {
@Override
public void handle1() {
//本狀态下必須處理的邏輯
}
@Override
public void handle2() {
//設定目前狀态為stat2
super.context.set Current State(Context.STATE2);
//過渡到state2狀态,由Context實作
super.context.handle2();
}
}
public class Concrete State2 extends State {
@Override
public void handle1() {
//設定目前狀态為state1
super.context.set Current State(Context.STATE1);
//過渡到state1狀态,由Context實作
super.context.handle1();
}
@Override
public void handle2() {
//本狀态下必須處理的邏輯
}
}
具體狀态角色有兩個職責:處理本狀态必須完成的任務,決定是否可以過渡到其他狀态。
//環境角色
public class Context {
//定義狀态
public final static State STATE1 = new Concrete State1();
public final static State STATE2 = new Concrete State2();
//目前狀态
private State Current State;
//獲得目前狀态
public State get Current State() {
return Current State;
}
//設定目前狀态
public void set Current State(State current State) {
this.Current State = current State;
//切換狀态
this.Current State.set Context(this);
}
//行為委托
public void handle1(){
this.Current State.handle1();
}
public void handle2(){
this.Current State.handle2();
}}
環境角色有兩個不成文的限制:
● 把狀态對象聲明為靜态常量,有幾個狀态對象就聲明幾個靜态常量。
● 環境角色具有狀态抽象角色定義的所有行為,具體執行使用委托方式。
場景類:
public class Client {
public static void main(String[] args) {
//定義環境角色
Context context = new Context();
//初始化狀态
context.set Current State(new Concrete State1());
//行為執行
context.handle1();
context.handle2();
}
}
如上所示:我們隻看到了行為發生改變。
狀态模式的優點:
● 結構清晰
避免了過多的switch...case或者if...else語句的使用,避免了程式的複雜性,提高系統的可維護性。
● 遵循設計原則
很好地展現了開閉原則和單一職責原則,每個狀态都是一個子類,你要增加狀态就要增加子類,你要修改狀态,你隻修改一個子類就可以了。
● 封裝性非常好
這也是狀态模式的基本要求,狀态變換放置到類的内部來實作,外部的調用不用知道類内部如何實作狀态和行為的變換。
狀态模式的缺點:
每一個狀态都是一個子類,容易産生子類膨脹的問題。
使用場景:
● 行為随狀态改變而改變的場景
這也是狀态模式的根本出發點,例如權限設計,人員的狀态不同即使執行相同的行為結果也會不同,在這種情況下需要考慮使用狀态模式。
● 條件、分支判斷語句的替代者