天天看點

Java設計模式—狀态模式

狀态模式又是一個比較難的設計模式 

定義如下:

當一個對象内在狀态改變時允許其改變行為,這個對象看起來像改變了其類。

個人了解:通俗的講,狀态模式就是狀态的改變引起了行為的改變,但是,我們隻能看到行為的改變,看不到狀态的改變。

通用類圖:

Java設計模式—狀态模式

角色介紹:

● 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語句的使用,避免了程式的複雜性,提高系統的可維護性。

● 遵循設計原則

很好地展現了開閉原則和單一職責原則,每個狀态都是一個子類,你要增加狀态就要增加子類,你要修改狀态,你隻修改一個子類就可以了。

● 封裝性非常好

這也是狀态模式的基本要求,狀态變換放置到類的内部來實作,外部的調用不用知道類内部如何實作狀态和行為的變換。

狀态模式的缺點:

每一個狀态都是一個子類,容易産生子類膨脹的問題。

使用場景:

● 行為随狀态改變而改變的場景

這也是狀态模式的根本出發點,例如權限設計,人員的狀态不同即使執行相同的行為結果也會不同,在這種情況下需要考慮使用狀态模式。

● 條件、分支判斷語句的替代者