說明:設計模式系列文章是讀劉偉
所著《設計模式的藝術之道(軟件開發人員內功修煉之道)》
一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的博客https://blog.csdn.net/LoveLion/article/details/17517213
。
模式概述
很多事物都具有多種狀態,而且在不同狀態下會具有不同的行爲,這些狀態在特定條件下還將發生相互轉換。就像水,它可以凝固成冰,也可以受熱蒸發後變成水蒸汽,水可以流動,冰可以雕刻,蒸汽可以擴散。
在軟件系統中,有些對象也像水一樣具有多種狀態,這些狀態在某些情況下能夠相互轉換,而且對象在不同的狀態下也將具有不同的行爲。爲了更好地對這些具有多種狀態的對象進行設計,可以使用一種被稱之爲狀態模式的設計模式——處理對象的多種狀態及其相互轉換。
在狀態模式中,將對象在每一個狀態下的行爲和狀態轉移語句封裝在一個個狀態類中,通過這些狀態類來分散冗長的條件轉移語句,讓系統具有更好的靈活性和可擴展性。
模式定義
狀態模式用於解決系統中複雜對象的狀態轉換以及不同狀態下行爲的封裝問題。當系統中某個對象存在多個狀態,這些狀態之間可以進行轉換,而且對象在不同狀態下行爲不相同時可以使用狀態模式。狀態模式將一個對象的狀態從該對象中分離出來,封裝到專門的狀態類中,使得對象狀態可以靈活變化,對於客戶端而言,無須關心對象狀態的轉換以及對象所處的當前狀態,無論對於何種狀態的對象,客戶端都可以一致處理。
狀態模式定義如下:
狀態模式(
State Pattern
):允許一個對象在其內部狀態改變時改變它的行爲,對象看起來似乎修改了它的類。其別名爲狀態對象(Objects for States
),狀態模式是一種對象行爲型模式。
模式結構圖
在狀態模式中引入了抽象狀態類和具體狀態類,它們是狀態模式的核心,其結構如下圖所示:
模式僞代碼
抽象狀態類典型代碼如下:
/**
* 抽象狀態
*/
public interface State {
/**
* 抽象狀態行爲1
*/
void action1();
/**
* 抽象狀態行爲2
*/
void action2();
}
不同的具體狀態類可以提供不同的實現,如下:
public class ConcreteState implements State {
@Override
public void action1() {
// 具體實現
}
@Override
public void action2() {
// 具體實現
}
}
環境類維持一個對抽象狀態類的引用,代碼大致如下:
public class Context {
// 抽象狀態
private State state;
// 該屬性值的變化可能會導致對象狀態發生變化
private int value;
public void setState(State state) {
this.state = state;
}
/**
* 狀態變化
*/
public void changeState() {
//判斷屬性值,根據屬性值進行狀態轉換
if (value == 0) {
this.setState(new ConcreteState());
} else if (value == 1) {
// this.setState(new ConcreteStateB());
} else {
// ...
}
}
/**
* 具體業務邏輯
*/
public void service() {
// ...
// 狀態行爲1
this.state.action1();
// 狀態行爲2
this.state.action2();
// ...
}
}
模式應用
待完善。
模式總結
狀態模式將一個對象在不同狀態下的不同行爲封裝在一個個狀態類中,通過設置不同的狀態對象可以讓環境對象擁有不同的行爲,而狀態轉換的細節對於客戶端而言是透明的,方便了客戶端的使用。
在實際開發中,狀態模式具有較高的使用頻率,在工作流和遊戲開發中狀態模式都得到了廣泛的應用,例如公文狀態的轉換、遊戲中角色的升級等。
主要優點
狀態模式可以避免使用龐大的條件語句來將業務方法和狀態轉換代碼交織在一起。
適用場景
- 對象的行爲依賴於它的狀態(如某些屬性值),狀態的改變將導致行爲的變化。
- 在代碼中包含大量與對象狀態有關的條件語句,這些條件語句的出現,會導致代碼的可維護性和靈活性變差,不能方便地增加和刪除狀態,並且導致客戶類與類庫之間的耦合增強。