狀態(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、狀態模式選擇一個狀態是會明顯告訴客戶端的,而策略模式則不會告訴客戶端選擇了什麼策略。
|
java狀態模式
第二章節 狀態模式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.