Stories

Detail Return Return

掌握設計模式--狀態模式 - Stories Detail

狀態模式(State Pattern)

狀態模式(State Pattern)是一種行為設計模式,它允許對象在其內部狀態改變時改變其行為,看起來像是改變了其類。這種模式通常用於解決對象在運行時狀態多變且行為複雜的問題。

核心思想:將狀態與行為綁定,每種狀態對應一個具體類有獨立的行為邏輯,狀態的切換隻需更換狀態對象,並且狀態流轉在行為邏輯中完成。

主要組成部分

  1. Context(上下文): 持有當前狀態的對象,負責將請求委託給當前狀態對象處理。

  2. State(抽象狀態): 定義一個接口,封裝具體狀態對象的行為。

  3. ConcreteState(具體狀態): 實現具體狀態對應的行為,每個狀態對應對象的一個行為。

案例實現

假設我們開發了一個簡單的文檔審批工作流系統,包括以下狀態:

  1. 草稿(Draft): 文檔創建後初始狀態,可編輯。
  2. 提交(Submitted): 文檔已提交,等待審批。
  3. 審批通過(Approved): 文檔被批准,不可再修改。
  4. 駁回(Rejected): 文檔被駁回,可重新編輯並提交。

案例類圖

image

狀態接口

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 審批駁回...
文檔審批通過
當前狀態: 審批通過 >>> 沒有其他操作。
當前狀態: 審批通過 >>> 沒有其他操作。
當前狀態: 審批通過 >>> 沒有其他操作。

擴展狀態:可以擴展為更多狀態,例如“待修改”、“歸檔”等,只需要增加具體狀態類及狀態流轉的調整即可。

優缺點和適用場景

優點

  1. 狀態切換清晰: 每個狀態封裝了特定行為,便於管理。
  2. 代碼維護性好: 避免了大量的 if-else 或 switch 語句。
  3. 遵循開閉原則: 添加新狀態時無需修改現有代碼。

缺點

  1. 狀態類增多: 每個狀態需要一個具體類,可能導致類的數量增加。
  2. 狀態切換複雜: 需要在狀態中顯式定義狀態轉換邏輯。

適用場景

  • 對象的行為取決於狀態,且需要在運行時根據狀態改變行為。
  • 替代 if-else 或 switch 語句處理狀態邏輯,避免代碼複雜性和維護困難。
  • 狀態之間的切換清晰明確、狀態轉換簡單且固定。

總結

狀態模式有點像策略模式,最大的不同是,狀態類維護着狀態的流轉

狀態模式是一種通過將對象的行為與其狀態分離,使對象在不同狀態下表現出不同行為的設計模式。在狀態中需要顯式定義狀態轉換邏輯,狀態模式的顯式狀態轉換邏輯適用於狀態數量有限、關係明確、行為獨立的場景,但在狀態複雜、依賴上下文或需要動態控制的情況下,應該引入更靈活的設計方式(如狀態機或規則引擎)來簡化管理。

可以結合具體業務需求,權衡模式的適用性和實現複雜度,選擇最合適的方案。

image

需要查看往期設計模式文章的,可以在個人主頁中或者文章開頭的集合中查看,可關注我,持續更新中。。。


超實用的SpringAOP實戰之日誌記錄

2023年下半年軟考考試重磅消息

通過軟考後卻領取不到實體證書?

計算機算法設計與分析(第5版)

Java全棧學習路線、學習資源和麪試題一條龍

軟考證書=職稱證書?

軟考中級--軟件設計師毫無保留的備考分享

Add a new Comments

Some HTML is okay.