定義
狀態模式(State Pattern):允許一個對象在其內部狀態改變時改變它的行爲。對象看起來似乎修改了它的類。
結構
- Context(環境類):環境類又稱爲上下文類,它是擁有多種狀態的對象。由於環境類的狀態存在多樣性且在不同狀態下對象的行爲有所不同,因此將狀態獨立出去形成單獨的狀態類。在環境類中維護一個抽象狀態類State的實例,這個實例定義當前狀態,在具體實現時它是一個State的子類對象。
- State(抽象狀態類):它用於定義一個接口以封裝與環境類的一個特定狀態相關的行爲,在抽象狀態類中聲明瞭各種不同狀態對象的方法,而在其子類中實現了這些方法,由於不同狀態下對象的行爲可能不同,因此在不同的子類中方法的實現可能存在不同,相同的方法可以寫在抽象狀態類中。
- ConcreteState(具體狀態類):它是抽象狀態類的子類,每一個子類實現一個與環境類的一個狀態相關的行爲,每一個具體狀態類對應環境的一個具體狀態,不同的具體狀態類的行爲有所不同。
代碼
State
public abstract class State {
// 抽象業務方法,不同的具體狀態可以有不同的實現
public abstract void handle();
}
ConcreteState1
public class ConcreteState1 extends State {
@Override
public void handle() {
System.out.println("ConcreteState1");
}
}
ConcreteState2
public class ConcreteState2 extends State {
@Override
public void handle() {
System.out.println("ConcreteState2");
}
}
Context
public class Context {
// 其他屬性,該屬性值變化可能回導致對象的狀態發生改變
private int value;
// 維持一個對抽象狀態的引用
private State state;
public void request() {
// 調用狀態對象的業務方法
state.handle();
}
// 統一由環境類來負責狀態之間的轉換
public void changeState() {
// 判斷屬性值,根據屬性值進行狀態轉換
if (value == 0) {
setState(new ConcreteState1());
} else if (value == 1) {
setState(new ConcreteState2());
}
}
public void setState(State state) {
this.state = state;
}
}
優/缺點與適用環境
- 優點
- 狀態模式封裝了狀態的轉換規則,在狀態模式中可以將狀態的轉換代碼封裝在環境類或者具體狀態類中,可以對狀態轉換代碼進行集中管理,而不是分散在一個個業務方法中。
- 狀態模式將所有與某個狀態有關的行爲放到一個類中,只需要注人一個不同的狀態對象即可使環境對象擁有不同的行爲。
- 狀態模式允許狀態轉換邏輯與狀態對象合成一體,而不是提供一個巨大的條件語句塊,狀態模式可以避免使用龐大的條件語句將業務方法和狀態轉換代碼交織在一起。
- 狀態模式可以讓多個環境對象共享一個狀態對象,從而減少系統中對象的個數。
- 缺點
- 狀態模式會增加系統中類和對象的個數,導致系統運行開銷增大。
- 狀態模式的結構與實現都較爲複雜,如果使用不當將導致程序結構和代碼的混亂,增加系統設計的難度。
- 狀態模式對開閉原則的支持並不太好,增加新的狀態類需要修改那些負責狀態轉換的源代碼,否則無法轉換到新增狀態,而且修改某個狀態類的行爲也需要修改對應類的源代碼。
- 適用環境
- 對象的行爲依賴於它的狀態(例如某些屬性值),狀態的改變將導致行爲的變化。
- 在代碼中包含大量與對象狀態有關的條件語句,這些條件語句的出現會導致代碼的可維護性和靈活性變差,不能方便地增加和刪除狀態,並且導致客戶類與類庫之間的耦合增強。