iT邦幫忙

2025 iThome 鐵人賽

DAY 8
1
生成式 AI

agent-brain: 從 0 開始打造一個 python package系列 第 8

Day 8: 先來看一下 State pattern

  • 分享至 

  • xImage
  •  

由於之後我打算使用 State patten 當作整個專案的主軸,在繼續往下實作之前,我們先來研究一下 State pattern 是什麼,並且帶來什麼好處?


狀態模式(State Pattern)

狀態模式有限狀態機(Finite-State Machine, FSM) 的概念密切相關。
其實就很像我們整個 LLM Agent 思考的流程中有不同的階段一樣,
e.g., decomposition state / action state / reflection state ...

https://ithelp.ithome.com.tw/upload/images/20250922/20128319KY76MnNSL3.png

範例情境

假設我們有一個 Document 類別。文件可以處於三種狀態之一:

https://ithelp.ithome.com.tw/upload/images/20250922/20128319K26A7dywrP.png

  • Draft(草稿)
  • Moderation(審核中)
  • Published(已發布)

每種狀態下的 publish 方法行為不同:

  • Draft 狀態:發佈會讓文件進入審核流程。
  • Moderation 狀態:僅當使用者為管理員時,文件才會公開。
  • Published 狀態:不會執行任何動作。

傳統實作問題

通常狀態機會使用許多 條件判斷(if 或 switch) 來根據狀態執行邏輯,例如:

class Document {
    String state;

    void publish() {
        switch (state) {
            case "draft":
                if (currentUser.role == "admin")
                    state = "published";
                if (currentUser.role == "author")
                    state = "moderation";
                break;
            case "moderation":
                if (currentUser.role == "admin")
                    state = "published";
                break;
            case "published":
                if (time.expire)
                    state = "draft";
                break;
        }
    }
}

或者就只能規畫好一種 workflow

draft -> moderation -> published 

缺點

  • 文件類別會隨著狀態數量與邏輯增加而變得複雜。
  • 任一狀態轉換邏輯的修改,都可能需要在多個地方更新條件式 → 維護困難。

Solution?

State pattern 將「每個State的行為」獨立成 Class,並把「狀態相關的邏輯」從 Document 類別中抽離。


範例程式碼

狀態介面

class State {
public:
    virtual void render(Document& document) = 0;
    virtual void publish(Document& document) = 0;
};

Document 類別

class Document {
private:
    std::shared_ptr<State> state;

public:
    Document(std::shared_ptr<State> initialState) : state(initialState) {}

    void render() { state->render(*this); }
    void publish() { state->publish(*this); }

    void changeState(std::shared_ptr<State> newState) {
        state = newState;
    }
};

Draft 狀態

class Draft : public State {
public:
    void render(Document& document) override {
        std::cout << "Rendering draft document...\n";
    }

    void publish(Document& document) override {
        if (document.isAdmin()) {
            document.changeState(std::make_shared<Published>());
            std::cout << "Document published from draft.\n";
        } else {
            document.changeState(std::make_shared<Moderation>());
            std::cout << "Document sent to moderation.\n";
        }
    }
};

Moderation 狀態

class Moderation : public State {
public:
    void render(Document& document) override {
        std::cout << "Rendering document in moderation...\n";
    }

    void publish(Document& document) override {
        std::cout << "Moderation state cannot publish directly.\n";
    }
};

Published 狀態

class Published : public State {
public:
    void render(Document& document) override {
        std::cout << "Rendering published document...\n";
    }

    void publish(Document& document) override {
        std::cout << "Document is already published.\n";
    }
};

優缺點

優點

  • 單一職責原則(SRP):每個狀態專注於自己的邏輯。
  • 開放封閉原則(OCP):新增狀態時不需改動原有程式。
  • 簡化 Document 類別,移除複雜條件判斷。

缺點

  • 若狀態數量少,或狀態轉換邏輯簡單,套用此模式可能顯得過度設計

與其他 design pattern 的關係

  • Bridge、State、Strategy、Adapter 在結構上相似,都是依靠組合(Composition)來委派工作。

  • State vs Strategy

    • Strategy 的策略彼此獨立、不知道對方存在。
    • State 的狀態之間則可以互相轉換,甚至能直接改變 Context 的狀態。

Takeaway

明天會來規劃好我打算怎麼實作每個 state

ref:
https://refactoring.guru/design-patterns/state


上一篇
Day 7: 從 uv 開始一個專案
下一篇
Day 9: LLM Agent 的 States (一)
系列文
agent-brain: 從 0 開始打造一個 python package9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言