由於之後我打算使用 State patten 當作整個專案的主軸,在繼續往下實作之前,我們先來研究一下 State pattern 是什麼,並且帶來什麼好處?
狀態模式
與 有限狀態機(Finite-State Machine, FSM) 的概念密切相關。
其實就很像我們整個 LLM Agent 思考的流程中有不同的階段一樣,
e.g., decomposition state / action state / reflection state ...
假設我們有一個 Document
類別。文件可以處於三種狀態之一:
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
缺點:
State pattern 將「每個State的行為」獨立成 Class,並把「狀態相關的邏輯」從 Document
類別中抽離。
class State {
public:
virtual void render(Document& document) = 0;
virtual void publish(Document& document) = 0;
};
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;
}
};
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";
}
}
};
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";
}
};
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";
}
};
Document
類別,移除複雜條件判斷。Bridge、State、Strategy、Adapter 在結構上相似,都是依靠組合(Composition)來委派工作。
State vs Strategy:
Strategy
的策略彼此獨立、不知道對方存在。State
的狀態之間則可以互相轉換,甚至能直接改變 Context 的狀態。明天會來規劃好我打算怎麼實作每個 state
ref:
https://refactoring.guru/design-patterns/state