允許一個物件在其內部狀態改變時改變它的行為。物件看起來好像修改了它的類別。

傳統做法在 Context 中用 switch(state) 分派行為,導致:
case 中,難以維護。State 模式將每種狀態封裝為獨立類別(ConcreteState),Context 委派給當前狀態物件處理請求,並由狀態物件負責轉移至下一狀態。
#ifndef STATE_H
#define STATE_H
class State;
class Context;
class Context {
public:
Context(State* pState);
~Context();
void Request();
void ChangeState(State* pState);
private:
State* m_pState;
};
class State {
public:
virtual ~State() {}
virtual void Handle(Context* pContext) = 0;
};
class ConcreteStateA : public State {
public:
void Handle(Context* pContext);
};
class ConcreteStateB : public State {
public:
void Handle(Context* pContext);
};
#endif
#include "State.h"
#include <iostream>
Context::Context(State* pState) : m_pState(pState) {}
Context::~Context() { delete m_pState; m_pState = nullptr; }
void Context::Request() {
if (m_pState) m_pState->Handle(this);
}
void Context::ChangeState(State* pState) {
if (m_pState) { delete m_pState; m_pState = nullptr; }
m_pState = pState;
}
void ConcreteStateA::Handle(Context* pContext) {
std::cout << "Handle by ConcreteStateA\n";
if (pContext) pContext->ChangeState(new ConcreteStateB()); // 切換狀態
}
void ConcreteStateB::Handle(Context* pContext) {
std::cout << "Handle by ConcreteStateB\n";
if (pContext) pContext->ChangeState(new ConcreteStateA()); // 切換回 A
}
#include "State.h"
int main() {
State* pState = new ConcreteStateA();
Context* pContext = new Context(pState);
pContext->Request(); // Handle by ConcreteStateA -> 切換到 B
pContext->Request(); // Handle by ConcreteStateB -> 切換到 A
pContext->Request(); // Handle by ConcreteStateA
delete pContext;
return 0;
}
| 維度 | State 模式 | Strategy 模式 |
|---|---|---|
| 封裝對象 | 狀態相關行為 | 演算法/策略 |
| 狀態轉移 | 由狀態物件內部主動發起 | 由客戶端/Context 顯式設定 |
| 適用場景 | 物件行為隨內部狀態頻繁變化(如 TCP 連線狀態、遊戲角色狀態) | 需在執行期動態切換演算法(如排序、壓縮、路徑規劃) |
| 結構相似度 | 極高(均為委派給抽象介面) | 極高 |