狀態模式(State Pattern)
狀態模式(State Pattern)是一種行為設計模式,它允許對象在其內部狀態改變時改變其行為,看起來像是改變了其類。這種模式通常用於解決對象在運行時狀態多變且行為複雜的問題。
核心思想:將狀態與行為綁定,每種狀態對應一個具體類有獨立的行為邏輯,狀態的切換隻需更換狀態對象,並且狀態流轉在行為邏輯中完成。
主要組成部分
-
Context(上下文): 持有當前狀態的對象,負責將請求委託給當前狀態對象處理。
-
State(抽象狀態): 定義一個接口,封裝具體狀態對象的行為。
-
ConcreteState(具體狀態): 實現具體狀態對應的行為,每個狀態對應對象的一個行為。
案例實現
假設我們開發了一個簡單的文檔審批工作流系統,包括以下狀態:
- 草稿(Draft): 文檔創建後初始狀態,可編輯。
- 提交(Submitted): 文檔已提交,等待審批。
- 審批通過(Approved): 文檔被批准,不可再修改。
- 駁回(Rejected): 文檔被駁回,可重新編輯並提交。
案例類圖
狀態接口
public interface State {
void handle(Context context);
}
具體狀態
一種狀態對應一個具體類,實現不同的行為邏輯,在行為中流轉到下一種狀態。
// 草稿狀態
public class DraftState implements State {
@Override
public void handle(Context context) {
System.out.println("當前狀態: 草稿狀態 >>> 提交文檔...");
context.setState(new SubmittedState());
}
}
// 提交狀態
public class SubmittedState implements State {
@Override
public void handle(Context context) {
System.out.println("當前狀態: 提交狀態 >>> 審批通過 or 審批駁回...");
// 模擬審批結果
if (Math.random() > 0.5) {
System.out.println("文檔審批通過");
context.setState(new ApprovedState());
} else {
System.out.println("文檔審批駁回");
context.setState(new RejectedState());
}
}
}
// 審批通過狀態
public class ApprovedState implements State {
@Override
public void handle(Context context) {
System.out.println("當前狀態: 審批通過 >>> 沒有其他操作。");
}
}
// 駁回狀態
public class RejectedState implements State {
@Override
public void handle(Context context) {
System.out.println("當前狀態: 駁回狀態 >>> 重新編輯並提交文檔...");
context.setState(new DraftState());
}
}
上下文類
狀態的流程由上下文類來完成
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
測試代碼
public class WorkflowStateDemo {
public static void main(String[] args) {
Context context = new Context(new DraftState());
// 模擬多次狀態變化
for (int i = 0; i < 5; i++) {
context.request();
}
}
}
運行結果
每次運行的結果可能不同,因為模擬了隨機審批結果:
當前狀態: 草稿狀態 >>> 提交文檔...
當前狀態: 提交狀態 >>> 審批通過 or 審批駁回...
文檔審批駁回
當前狀態: 駁回狀態 >>> 重新編輯並提交文檔...
當前狀態: 草稿狀態 >>> 提交文檔...
當前狀態: 提交狀態 >>> 審批通過 or 審批駁回...
文檔審批通過
或
當前狀態: 草稿狀態 >>> 提交文檔...
當前狀態: 提交狀態 >>> 審批通過 or 審批駁回...
文檔審批通過
當前狀態: 審批通過 >>> 沒有其他操作。
當前狀態: 審批通過 >>> 沒有其他操作。
當前狀態: 審批通過 >>> 沒有其他操作。
擴展狀態:可以擴展為更多狀態,例如“待修改”、“歸檔”等,只需要增加具體狀態類及狀態流轉的調整即可。
優缺點和適用場景
優點
- 狀態切換清晰: 每個狀態封裝了特定行為,便於管理。
- 代碼維護性好: 避免了大量的 if-else 或 switch 語句。
- 遵循開閉原則: 添加新狀態時無需修改現有代碼。
缺點
- 狀態類增多: 每個狀態需要一個具體類,可能導致類的數量增加。
- 狀態切換複雜: 需要在狀態中顯式定義狀態轉換邏輯。
適用場景
- 對象的行為取決於狀態,且需要在運行時根據狀態改變行為。
- 替代 if-else 或 switch 語句處理狀態邏輯,避免代碼複雜性和維護困難。
- 狀態之間的切換清晰明確、狀態轉換簡單且固定。
總結
狀態模式有點像策略模式,最大的不同是,狀態類維護着狀態的流轉
狀態模式是一種通過將對象的行為與其狀態分離,使對象在不同狀態下表現出不同行為的設計模式。在狀態中需要顯式定義狀態轉換邏輯,狀態模式的顯式狀態轉換邏輯適用於狀態數量有限、關係明確、行為獨立的場景,但在狀態複雜、依賴上下文或需要動態控制的情況下,應該引入更靈活的設計方式(如狀態機或規則引擎)來簡化管理。
可以結合具體業務需求,權衡模式的適用性和實現複雜度,選擇最合適的方案。
需要查看往期設計模式文章的,可以在個人主頁中或者文章開頭的集合中查看,可關注我,持續更新中。。。
超實用的SpringAOP實戰之日誌記錄
2023年下半年軟考考試重磅消息
通過軟考後卻領取不到實體證書?
計算機算法設計與分析(第5版)
Java全棧學習路線、學習資源和麪試題一條龍
軟考證書=職稱證書?
軟考中級--軟件設計師毫無保留的備考分享