設計模式--狀態模式(State)
前幾天由于忙工作上的事情,每天加班到10點左右才回家,回到家就沒有再開電腦更新東西,今天早了一些回家,開始繼續更新東西,今天要寫的是狀態模式,哦,對于一個沒有狀態的人來說,寫狀態模式,不知道會寫成什么樣子,反正是一起討論用嘛,能把我所知道的清楚表達出來已經很心滿意足啦。在理解狀態模式的時候,我總覺得它和策略模式很像很像,有人說它們是孿生兄弟,那我們現在看看狀態模式到底是一個什么樣的東西。
狀態模式是對象的一個行為模式,它允許一個對象在其內部狀態改變的時候改變其行為,這個對象看上去就像改了了它的類一樣。
下圖是關于紅綠燈轉換的一個實現類圖,具體的轉換是這樣子的,在初始的情況下,設定一個燈的狀態,比如是綠燈,那么燈的下一個狀態則是黃燈,緊接著是紅燈,然后再是綠燈,依次循環;通過改變燈的狀態,改變其行為。
下面是這個類圖的實現代碼:
package com.plabmedia.state;
public interface LightState {
/**
* 打印當前的狀態
*/
public void print(Light light);}
package com.plabmedia.state;
public class RedLight implements LightState{
@Override
public void print(Light light) {
System.out.println("current state is red");
light.setState(new GreenLight());
}}
package com.plabmedia.state;
public class YellowLight implements LightState{
@Override
public void print(Light light) {
System.out.println("current state is yellow");
light.setState(new RedLight());
}}
package com.plabmedia.state;
public class GreenLight implements LightState {
@Override
public void print(Light light) {
System.out.println("current state is green");
light.setState(new YellowLight());
}}
package com.plabmedia.state;
public class Light {
private LightState state;
public LightState getState() {
return state;
}public void setState(LightState state) {
this.state = state;
}public void print(){
state.print(this);
}public Light(LightState state){
this.state = state;
}}
package com.plabmedia.state;
public class Client {
public static void main(String args[]){
Light light = new Light(new GreenLight());
light.print();
light.print();
light.print();
light.print();
light.print();
light.print();
}}
運行結果:
current state is green
current state is yellow
current state is red
current state is green
current state is yellow
current state is red
上面是對狀態模式一個小小的實現,這個實現也僅僅是認識級的,在我們實際應用中,如果用到狀態模式,應該比這個要負責的多,只是基本的結構是相似的。那我們下面針對狀態模式做一些討論。
1.在什么情況下使用狀態模式:
- 一個對象的行為依賴于它所處的狀態,對象的行為必須隨著其狀態的改變而改變;
- 需要多多重條件轉移語句進行演化的時候,可以把每個分支封裝成一個狀態類;現在寫代碼的時候,我是不太喜歡用條件轉移語句,特別是最好的那個else語句,我覺得它承擔的東西太多了,前面不滿足的情況它都要來處理,憑什么啊。
- 誰來定義狀態的變化:客戶端還是狀態內部決定?這要看當時應用的環境,如果狀態的變化是固定的,我覺得可以再客戶端進行設定;如果狀態的變化依賴于前一個狀態,比如在工作流系統中,當前狀態是依賴于前一個狀態的,這需要狀態內部來覺得。
- 狀態對象創建時機:需要的時候創建?還是事先創建好所有的對象,供需要的時候調用?這要分系統需要來決定,如果一個系統,狀態變化的順序固定,不那么頻繁,則可以在需要的時候創建所需要的對象;否則,對于頻繁變化的狀態,從性能上將,還是首先創建好各個狀態對象,供需要時調用。
- 可以把環境類傳到具體的狀態類中,狀態類在需要的時候調用環境類,比如示例中的樣子,其實在每個狀態類里面,也可以直接調用環境類的print方法,這樣看來,Client只需要初始化環境類,然后就可以看到它的狀態在不停地變化。