java狀態模式

第二章節   狀態模式
       狀態(state)模式:狀態模式的意圖是,允許一個對象在其內部狀改變時改變它的行爲。看起來就像是改變了它的類一樣。主要解決的是當控制一個對象
狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同的一系列類當中,可以把複雜的邏輯判斷簡單化。首先咱們還是先看下GOF對狀
態模式的定義:當一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。狀態模式中的行爲是由狀態來決定的,不同的狀態對應了不
同的行爲。狀態模式和策略模式的結構幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行爲是平行的不可替換的,策略模式的行爲是彼此獨立
可相互替換的。
----------------------------------------------------------------------------------------------------------------------------------------------------------
狀態模式的結構如下圖:

從圖中可以看出狀態模式有以下角色:
------------------------------------------------------------------------------------
1、抽象狀態(State)角色:定義一個接口,用以封裝環境對象的一個特定的狀態所對應的行爲。
2、具體狀態(ConcreteState)角色:每一個具體狀態類都實現了環境的一個狀態所對的行爲。
3、場景(Context)角色:定義客戶端所感興趣的接口,並且保留一個具體狀態類的實例。這個具體狀態類的實例給出此環境對象現有的狀態。
上圖用代碼模擬如下:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
public interface State {  
    public void change(Context context);  
}  

public class ConcreteStateA implements State {  
  
    @Override  
    public void change(Context context) {  
        System.out.println("this is ConcreteStateA");  
        context.setState(new ConcreteStateB());  
    }  
}  

public class ConcreteStateB implements State {  
  
    @Override  
    public void change(Context context) {  
        System.out.println("this is ConcreteStateB");  
        context.setState(new ConcreteStateA());  
    }  
}  

具體的Context 類:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
package state;  
 
public class Context {  
   
    private State state;  
      
    public void change(){  
        state.change(this);  
    }  
      
  
    public Context(State state) {  
        super();  
        this.state = state;  
    }  
  
  
    public State getState() {  
        return state;  
    }  
  
  
    public void setState(State state) {  
        this.state = state;  
    }  
}  
---------------------------------------------------------------------------------------------------------------------------------------------------
public class Client {  
  
    /** 
     *作者:alaric 
     *時間:2013-9-3下午7:52:05 
     *描述: 
     */  
    public static void main(String[] args) {  
          
        State state = new ConcreteStateA();  
        Context context = new Context(state);  
        //初始狀態是A  
        context.change();  
        //裝換一次後變成B  
        context.change();  
        //再轉換一次後又變成A  
        context.change();  
    }  
}  
運行結果如下:
this is ConcreteStateA
this is ConcreteStateB
this is ConcreteStateA
        上面代碼是兩個狀態切換,很符合家裏燈的開關,A表示關,B表示開,按一下打開,再按一下關閉。下面舉個例子,馬路上的紅綠燈大家都知道的,它有三個狀態控制三個不同顏色的燈,我們分別用RedState(紅燈狀態),GreenState(綠燈狀態),YellowState(黃燈狀態)表示三個燈的狀態,用Light表示燈來模擬,類圖如下:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


---------------------------------------------------------------------------------------------------------------------------
狀態模式的角色:
(1)上下文環境(Context):它定義了客戶程序需要的接口並維護一個具體狀態角色的實例,將與狀態相關的操作委託
          給當前的Concrete State對象來處理。 
(2)抽象狀態角色(State):定義一個接口以封裝使用上下文環境的的一個特定狀態相關的行爲。
(3)具體狀態角色(ConcreteState):實現抽象狀態定義的接口。
---------------------------------------------------------------------------------------------------------------------------

public interface State { 
    public void change(Light light);  
  //  具體的情況如下所示:
---------------------------------------------------------------------------------------------------------------------------
public class GreenState implements State { 
 
    private static final Long SLEEP_TIME = 2000L;  
    @Override  
    public void change(Light light) {  
          
        System.out.println("現在是綠燈,可以通行");  
        //綠燈亮1秒  
        try {  
            Thread.sleep(SLEEP_TIME);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        light.setState(new YellowState());  
    }  
  
}  
---------------------------------------------------------------------------------------------------------------------------
public class YellowState implements State {  

    private static final Long SLEEP_TIME = 500L;  
    @Override  
    public void change(Light light) {  
          
        System.out.println("現在是黃燈,警示");  
        //紅燈亮0.5秒  
        try {  
            Thread.sleep(SLEEP_TIME);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        light.setState(new RedState());  
    }  
}  
---------------------------------------------------------------------------------------------------------------------------
public class RedState implements State {  

    private static final Long SLEEP_TIME = 1000L;  
    @Override  
    public void change(Light light) {  
  
        System.out.println("現在是紅燈,禁止通行");  
        //紅燈亮1秒  
        try {  
            Thread.sleep(SLEEP_TIME);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        light.setState(new GreenState());  
    }  
}  
------------------------------------------------------------------------------------------------------------------------------
public class Light {  
  
    private State state;  
      
    private void change(){  
        state.change(this);  
    }  
  
    public void work(){  
        while(true){  
            change();  
        }  
    }  

    public Light(State state) {  
        super();  
        this.state = state;  
    }  
  
    public State getState() {  
        return state;  
    }  
  
    public void setState(State state) {  
        this.state = state;  
    }  
      
}  
----------------------------------------------------------------------------------------------------------------------------
public static void main(String[] args) {  
          
        //假設路燈開始是綠燈  
        State state = new GreenState();  
        Light light = new Light(state);  
        light.work();   
    }  
---------------------------------------------------------------------------------------------------------------------------
運行結果:
現在是綠燈,可以通行
現在是黃燈,警示
現在是紅燈,禁止通行
現在是綠燈,可以通行
現在是黃燈,警示
現在是紅燈,禁止通行
現在是綠燈,可以通行
現在是黃燈,警示
.....
       通過上面例子可以看出,狀態模式將與特定狀態相關的行爲局部化,並且將不同狀態的行爲分割開來;所有狀態相關的代碼都存
在於某個ConcereteState中,所以通過定義新的子類很容易地增加新的狀態和轉換;狀態模式通過把各種狀態轉移邏輯分不到State
的子類之間,來減少相互間的依賴。缺點是:會導致有很多State 的子類。

狀態模式和策略模式結構完全一樣,很容易混淆,這裏列舉下狀態模式和策略模式的區別:
------------------------------------------------------------------------------------------------------------------------------------------------
1、狀態模式有明顯的狀態過渡,從一個狀態到另一個狀態轉換過程,在整個生命週期裏有多個狀態轉換;而策略模式一旦環境角色選擇了
     一個具體的策略類,那麼在整個生命週期它始終不會改變;
2、狀態模式多數是外在原因在環境角色中放入一個具體的狀態類,而策略模式是自主選擇一個具體的策略類;
3、狀態模式選擇一個狀態是會明顯告訴客戶端的,而策略模式則不會告訴客戶端選擇了什麼策略。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章