狀態( State )模式:允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。

適用性:

  • 一個對象的行為取決于它的狀態, 并且它必須在運行時刻根據狀態改變它的行為。
  • 一個操作中含有龐大的多分支的條件語句,且這些分支依賴于該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴于其他對象而獨立變化。

所涉及的角色:

抽象狀態 (State) 角色:定義一個接口,用以封裝對象的一個特定狀態所對應的形為。

具體狀態 (Concrete State) 角色:每一個具體狀態類都實現環境( Context )的一個狀態所對應的行為。

環境( Context )角色:定義客戶端所感興趣的接口,并且保留一個具體狀態類的實例。這個具體狀態類的實例給出些環境對象的現有狀態。
state.bmp
一個簡單的例子:

抽象狀態State類

package ?State;

public ? interface ?State {
????
// 接口方法
???? void ?operator();
}


具體狀態類ConcreteStateA和ConcreteStateB:

package ?State;

public ? class ?ConcreteStateA? implements ?State {
????
// 實現接口方法
???? public ? void ?operator() {
????????System.out.println(
" The?ConcreteStateA " );
????}

}
package ?State;

public ? class ?ConcreteStateB? implements ?State {
????
// 實現接口方法
???? public ? void ?operator() {
????????System.out.println(
" The?ConcreteStateB " );
????}

}

環境Context類
package?State;

public?class?Context{
????
private?State?state;
????
//狀態賦值方法
????public?void?setState(State?state){
????????
this.state=state;
????}

????
//委派方法
????public?void?operator(){
????????state.operator();
????}

}
客戶端類:
package?State;

public?class?Client{
????
private?static?State?state=null;
????
private?static?Context?context=null;
????
????
public?static?void?main(String[]?args){
????????
????????context
=new?Context();
????????state
=new?ConcreteStateA();
????????context.setState(state);
????????context.operator();
????????state
=new?ConcreteStateB();
????????context.setState(state);
????????context.operator();
????}

}

狀態模式與策略模式的區別:

兩個模式很容易混淆,區別兩者的一個方法是考察環境角色是否有明顯的狀態和狀態過渡。如果環境角色只有一個狀態,那么就應當使用策略模式。策略模式的特點:一旦環境角色選擇了一個具體的策略類,那么在整個環境類的生命周期里它都不會改變這個具體策略類。而狀態模式則適用另一情況,即環境角色有明顯的狀態轉移。在環境類的生命周期里面,會有幾個不同的狀態被使用。

另外一個微妙的區別在于策略模式的環境自己選擇一個具體的策略類,而狀態模式的環境類是被外在原因放進一個具體的狀態中。

策略模式所選擇的策略類往往不明顯的告訴客戶端它所選擇的具體策略類,而狀態模式則相反,環境角色所處的狀態是明顯告訴客戶端的。

參考資料:《java與模式》
《設計模式速查手冊》
http://blog.csdn.net/qutr/archive/2006/08/01/1007617.aspx