第一部分:基础概念与实现
一、概念定义
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为,看起来就像是改变了它的类一样。
核心思想:将状态相关的行为封装在独立的状态类中,并将状态切换逻辑从主对象中分离出来。
二、模式结构
可能改变状态
可能改变状态
Context
-State* state
+request()
+setState(State* state)
<<abstract>>
State
+handle(Context* context)
ConcreteStateA
+handle(Context* context)
ConcreteStateB
+handle(Context* context)
三、核心角色
- Context(环境类):维护一个State实例,定义当前状态
- State(抽象状态类):定义一个接口封装与特定状态相关的行为
- ConcreteState(具体状态类):实现抽象状态接口的具体行为
四、应用场景
适用场景
- 对象的行为依赖其状态,并且运行时状态会改变
- 有大量的条件语句(if-else或switch-case)依赖于对象状态
- 状态转换逻辑复杂,需要显式管理
- 多个状态共享相同的行为,通过继承复用代码
实际案例
- 订单状态(待支付、已支付、已发货、已完成、已取消)
- 电梯状态(运行、停止、维修、故障)
- TCP连接状态(已建立、监听、关闭)
- 游戏角色状态(站立、奔跑、跳跃、游泳、死亡)
- 工作流审批状态
五、C++代码示例
示例1:电梯系统
cpp
#include <iostream>
#include <memory>
#include <string>
using namespace std;
// 前向声明
class ElevatorContext;
// 抽象状态类
class ElevatorState {
public:
virtual ~ElevatorState() = default;
virtual void openDoor(ElevatorContext* context) = 0;
virtual void closeDoor(ElevatorContext* context) = 0;
virtual void run(ElevatorContext* context) = 0;
virtual void stop(ElevatorContext* context) = 0;
virtual string getStateName() = 0;
};
// 环境类
class ElevatorContext {
private:
unique_ptr<ElevatorState> currentState;
public:
ElevatorContext(unique_ptr<ElevatorState> initialState)
: currentState(move(initialState)) {}
void setState(unique_ptr<ElevatorState> state) {
currentState = move(state);
cout << "电梯状态变为: " << currentState->getStateName() << endl;
}
void openDoor() {
currentState->openDoor(this);
}
void closeDoor() {
currentState->closeDoor(this);
}
void run() {
currentState->run(this);
}
void stop() {
currentState->stop(this);
}
};
// 具体状态类:停止状态
class StopState : public ElevatorState {
public:
void openDoor(ElevatorContext* context) override {
cout << "电梯已停止,可以开门" << endl;
// 转换到开门状态
// context->setState(make_unique<OpenState>());
}
void closeDoor(ElevatorContext* context) override {
cout << "电梯门已关闭" << endl;
}
void run(ElevatorContext* context) override {
cout << "电梯开始运行" << endl;
// 转换到运行状态
// context->setState(make_unique<RunState>());
}
void stop(ElevatorContext* context) override {
cout << "电梯已经处于停止状态" << endl;
}
string getStateName() override {
return "停止状态";
}
};
// 运行状态
class RunState : public ElevatorState {
public:
void openDoor(ElevatorContext* context) override {
cout << "电梯运行时不能开门!" << endl;
}
void closeDoor(ElevatorContext* context) override {
cout << "电梯门已关闭,继续运行" << endl;
}
void run(ElevatorContext* context) override {
cout << "电梯正在运行中" << endl;
}
void stop(ElevatorContext* context) override {
cout << "电梯停止运行" << endl;
context->setState(make_unique<StopState>());
}
string getStateName() override {
return "运行状态";
}
};
// 使用示例
int main() {
// 初始状态为停止状态
auto elevator = make_unique<ElevatorContext>(make_unique<StopState>());
elevator->run(); // 尝试运行
elevator->stop(); // 停止
elevator->openDoor(); // 开门
elevator->closeDoor();// 关门
return 0;
}
示例2:订单状态机(完整示例)
cpp
#include <iostream>
#include <memory>
#include <string>
#include <map>
#include <functional>
using namespace std;
class OrderContext;
// 订单状态枚举
enum class OrderStateType {
PENDING, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
DELIVERED, // 已送达
CANCELLED // 已取消
};
// 抽象状态类
class OrderState {
public:
virtual ~OrderState() = default;
virtual void pay(OrderContext* context) = 0;
virtual void ship(OrderContext* context) = 0;
virtual void deliver(OrderContext* context) = 0;
virtual void cancel(OrderContext* context) = 0;
virtual OrderStateType getType() const = 0;
virtual string getDescription() const = 0;
};
// 环境类
class OrderContext {
private:
unique_ptr<OrderState> currentState;
map<string, string> orderInfo;
public:
OrderContext(unique_ptr<OrderState> initialState)
: currentState(move(initialState)) {}
void setState(unique_ptr<OrderState> state) {
currentState = move(state);
cout << "订单状态变更为: " << currentState->getDescription() << endl;
}
OrderStateType getCurrentStateType() const {
return currentState->getType();
}
void pay() {
cout << "执行支付操作..." << endl;
currentState->pay(this);
}
void ship() {
cout << "执行发货操作..." << endl;
currentState->ship(this);
}
void deliver() {
cout << "执行送达操作..." << endl;
currentState->deliver(this);
}
void cancel() {
cout << "执行取消操作..." << endl;
currentState->cancel(this);
}
void setOrderInfo(const string& key, const string& value) {
orderInfo[key] = value;
}
string getOrderInfo(const string& key) const {
auto it = orderInfo.find(key);
return it != orderInfo.end() ? it->second : "";
}
};
// 待支付状态
class PendingState : public OrderState {
public:
void pay(OrderContext* context) override {
cout << "支付成功,订单状态变为已支付" << endl;
// 这里可以调用外部支付接口
context->setState(make_unique<PaidState>());
}
void ship(OrderContext* context) override {
cout << "错误:订单未支付,不能发货" << endl;
}
void deliver(OrderContext* context) override {
cout << "错误:订单未支付,不能确认送达" << endl;
}
void cancel(OrderContext* context) override {
cout << "订单已取消" << endl;
context->setState(make_unique<CancelledState>());
}
OrderStateType getType() const override {
return OrderStateType::PENDING;
}
string getDescription() const override {
return "待支付";
}
};
// 已支付状态
class PaidState : public OrderState {
public:
void pay(OrderContext* context) override {
cout << "错误:订单已支付,不能重复支付" << endl;
}
void ship(OrderContext* context) override {
cout << "订单已发货" << endl;
context->setState(make_unique<ShippedState>());
}
void deliver(OrderContext* context) override {
cout << "错误:订单未发货,不能确认送达" << endl;
}
void cancel(OrderContext* context) override {
cout << "订单已取消,将发起退款" << endl;
context->setState(make_unique<CancelledState>());
}
OrderStateType getType() const override {
return OrderStateType::PAID;
}
string getDescription() const override {
return "已支付";
}
};
// 已发货状态
class ShippedState : public OrderState {
public:
void pay(OrderContext* context) override {
cout << "错误:订单已发货,不能重复支付" << endl;
}
void ship(OrderContext* context) override {
cout << "错误:订单已发货,不能重复发货" << endl;
}
void deliver(OrderContext* context) override {
cout << "订单已送达" << endl;
context->setState(make_unique<DeliveredState>());
}
void cancel(OrderContext* context) override {
cout << "错误:订单已发货,不能取消,请联系客服处理" << endl;
}
OrderStateType getType() const override {
return OrderStateType::SHIPPED;
}
string getDescription() const override {
return "已发货";
}
};
// 已送达状态
class DeliveredState : public OrderState {
public:
void pay(OrderContext* context) override {
cout << "错误:订单已完成,无需支付" << endl;
}
void ship(OrderContext* context) override {
cout << "错误:订单已完成,无需发货" << endl;
}
void deliver(OrderContext* context) override {
cout << "错误:订单已完成" << endl;
}
void cancel(OrderContext* context) override {
cout << "错误:订单已完成,不能取消" << endl;
}
OrderStateType getType() const override {
return OrderStateType::DELIVERED;
}
string getDescription() const override {
return "已送达";
}
};
// 已取消状态
class CancelledState : public OrderState {
public:
void pay(OrderContext* context) override {
cout << "错误:订单已取消,无法支付" << endl;
}
void ship(OrderContext* context) override {
cout << "错误:订单已取消,无法发货" << endl;
}
void deliver(OrderContext* context) override {
cout << "错误:订单已取消,无法确认送达" << endl;
}
void cancel(OrderContext* context) override {
cout << "错误:订单已取消" << endl;
}
OrderStateType getType() const override {
return OrderStateType::CANCELLED;
}
string getDescription() const override {
return "已取消";
}
};
// 使用示例
int main() {
cout << "=== 订单状态机示例 ===" << endl;
// 创建订单,初始状态为待支付
auto order = make_unique<OrderContext>(make_unique<PendingState>());
cout << "\n--- 正常流程 ---" << endl;
order->pay(); // 支付
order->ship(); // 发货
order->deliver(); // 送达
cout << "\n--- 异常流程:未支付直接发货 ---" << endl;
auto order2 = make_unique<OrderContext>(make_unique<PendingState>());
order2->ship(); // 尝试直接发货(会被拒绝)
cout << "\n--- 取消流程 ---" << endl;
auto order3 = make_unique<OrderContext>(make_unique<PendingState>());
order3->cancel(); // 取消订单
return 0;
}
示例3:状态转换图
支付
取消
发货
取消(退款)
确认送达
退货(特殊流程)
完成
终止
待支付
已支付
已取消
已发货
已送达
第二部分:深层思维思想
六、核心哲学思想
1. "将变化封装在对象内部"的极致体现
状态模式最深刻的思维是:让事物的行为跟随其内在本质(状态)的变化而变化。
cpp
// 传统思维:外部判断
if (state == "pending") {
// 处理待支付逻辑
} else if (state == "paid") {
// 处理已支付逻辑
}
// 状态模式思维:让对象自己知道如何表现
state->handle(); // 不同的状态对象自然有不同的行为
思想精髓:不是"我根据你的状态来决定你该做什么",而是"你根据你自己的状态来决定你该做什么"。
2. "分而治之"思想
将复杂的条件逻辑按照"状态"这个维度进行切分:
复杂的状态相关逻辑
状态1的所有行为
状态2的所有行为
状态3的所有行为
行为A的实现
行为B的实现
行为C的实现
七、思维转变:从"过程式"到"对象式"
对比示例:交通灯系统
传统过程式思维:
cpp
// 思考角度:我如何控制这个流程?
class TrafficLight {
int state; // 0=红灯,1=绿灯,2=黄灯
void change() {
if (state == 0) {
// 红灯逻辑
wait(30);
state = 1;
} else if (state == 1) {
// 绿灯逻辑
wait(25);
state = 2;
} else if (state == 2) {
// 黄灯逻辑
wait(5);
state = 0;
}
}
};
状态模式思维:
cpp
// 思考角度:每个状态自己知道如何表现和转换
class RedLight : public LightState {
void show() override {
cout << "🔴 红灯,禁止通行" << endl;
}
void next(LightContext* ctx) override {
wait(30);
ctx->setState(new GreenLight()); // 红灯知道下一个是绿灯
}
};
class GreenLight : public LightState {
void show() override {
cout << "🟢 绿灯,请通行" << endl;
}
void next(LightContext* ctx) override {
wait(25);
ctx->setState(new YellowLight()); // 绿灯知道下一个是黄灯
}
};
思维差异:
- 过程式:外部控制,状态是数据
- 状态模式:内部自治,状态是行为载体
八、与自然世界的类比理解
1. 水的状态变化
0°C以下
0-100°C
100°C以上
加热
加热
冷却
冷却
水分子H2O
温度决定状态
固态冰
液态水
气态蒸汽
思想映射:
- 水分子 = Context(上下文)
- 固态/液态/气态 = ConcreteState
- 温度变化 = 事件触发状态转换
- 水的行为 = 状态决定(冰能雕刻,水能流动,蒸汽能扩散)
2. 人的情绪状态
cpp
// 情绪状态接口
class Emotion {
public:
virtual void express() = 0;
virtual void reactToEvent(const string& event) = 0;
};
class Happy : public Emotion {
void express() override {
cout << "😊 微笑,积极乐观" << endl;
}
void reactToEvent(const string& event) override {
if (event == "批评") {
cout << "乐观面对,自我改进" << endl;
} else if (event == "表扬") {
cout << "更加开心,继续努力" << endl;
}
}
};
class Angry : public Emotion {
void express() override {
cout << "😠 皱眉,易怒" << endl;
}
void reactToEvent(const string& event) override {
if (event == "批评") {
cout << "愤怒反驳,情绪激动" << endl;
} else if (event == "表扬") {
cout << "情绪平复,逐渐冷静" << endl;
}
}
};
九、核心思维模式的深度剖析
1. "状态即行为"的思维
传统编程常把状态视为属性 (一个变量),而状态模式把状态视为能力(一组方法)。
cpp
// 传统思维:状态是数据
class Document {
string status; // "draft", "review", "published"
void submit() {
if (status == "draft") {
// 提交逻辑
status = "review";
}
}
};
// 状态模式思维:状态是行为集合
class Document {
State* currentState; // 指向行为集合
void submit() {
currentState->submit(this); // 委托给状态对象
}
};
2. "责任转移"思维
将"决策责任"从Context转移到State:
状态模式
只负责委托
Context
State接口
State1
自己的决策
State2
自己的决策
State3
自己的决策
传统模式
承担所有决策
Context
if-else迷宫
3. "开闭原则"的完美体现
cpp
// 要增加新状态,无需修改现有代码
class NewState : public State {
void handle() override {
// 只需添加新类
}
};
// 传统方式需要修改所有条件判断
void oldWay() {
if (state == OLD_STATE1) {
// ...
} else if (state == OLD_STATE2) {
// ...
} else if (state == NEW_STATE) { // ❌ 修改了现有代码
// ...
}
}
十、状态模式 vs 策略模式
很多开发者容易混淆,但它们的思维本质不同:
| 维度 | 状态模式 | 策略模式 |
|---|---|---|
| 思维核心 | "我是什么,我就怎么做" | "我要什么,我就用什么方式" |
| 状态来源 | 内在的、自发的 | 外在的、选择的 |
| 状态转换 | 自动转换 | 手动切换 |
| 类比 | 人的情绪(你无法随意切换) | 工具选择(你可以随意选择) |
cpp
// 状态模式:情绪状态(自动转换)
class Person {
EmotionState* emotion;
void receiveMessage(const string& msg) {
emotion->react(msg); // 情绪自动反应
// 情绪可能会自动改变
}
};
// 策略模式:出行策略(主动选择)
class Traveler {
TransportStrategy* strategy;
void setStrategy(TransportStrategy* s) {
strategy = s; // 主动选择策略
}
void goToWork() {
strategy->travel(); // 使用选定的策略
}
};
十一、状态转换的思维模式
1. 集中式转换思维
所有转换逻辑集中在一个地方:
cpp
class StateMachine {
map<pair<State, Event>, State> transitions;
void handleEvent(Event e) {
State next = transitions[{currentState, e}];
currentState = next;
}
};
2. 分布式转换思维
每个状态知道自己的下一个状态:
cpp
class DraftState : public State {
void submit(Context* ctx) override {
// 草稿状态知道提交后进入审核状态
ctx->setState(new ReviewState());
}
};
选择建议:
- 集中式:状态多、转换规则复杂、需要统一管理
- 分布式:状态少、转换规则清晰、希望保持封装性
十二、思维训练:从状态模式到状态机思维
状态模式培养的是一种状态机思维,这种思维可以应用到更广的领域:
1. 业务流程设计
需求确认
设计完成
开发完成
测试通过
需求分析
设计
开发
测试
上线
2. 用户会话管理
- 未登录 → 浏览中 → 购物车 → 下单中 → 支付中 → 已完成
3. 设备状态管理
- 待机 → 运行 → 休眠 → 故障 → 维修中
十三、反模式与思维陷阱
❌ 陷阱1:过度设计
cpp
// 只有2个状态的简单场景也使用状态模式
class OnOffState { }; // 过度设计
class Light {
bool isOn; // 一个bool就够了
};
❌ 陷阱2:状态类携带大量数据
cpp
class StateWithData {
string data1, data2, data3; // 不应该存储在状态中
Context* ctx; // 数据应该在Context中
};
❌ 陷阱3:状态转换混乱
cpp
class StateA {
void handle(Context* ctx) {
if (someCondition) {
ctx->setState(new StateB());
} else if (otherCondition) {
ctx->setState(new StateC());
} else if (complexCondition) {
ctx->setState(new StateD()); // 转换逻辑过于复杂
}
}
};
十四、优缺点分析
优点
- 单一职责原则:将不同状态的行为分离到不同的类中
- 开闭原则:增加新状态只需添加新的状态类
- 消除条件语句:用多态替代复杂的if-else或switch
- 状态转换显式化:状态转换逻辑更清晰
- 代码可维护性强:状态相关代码集中在具体状态类中
缺点
- 类膨胀:每个状态都需要一个具体类
- 状态转换分散:状态转换逻辑可能分布在多个状态类中
- 上下文与状态耦合:状态类需要持有上下文的引用
- 复杂度增加:对于简单状态机可能过度设计
十五、最佳实践建议
-
何时使用:
- 对象的行为取决于其状态
- 有大量的条件判断基于状态
- 状态数量有限且明确
-
实现技巧:
- 考虑使用状态表代替多个状态类
- 使用单例模式实现无状态的状态对象
- 结合工厂模式创建状态对象
- 使用智能指针管理状态对象生命周期
-
性能考虑:
- 避免频繁创建状态对象
- 无状态的状态类可使用单例
- 状态转换要高效
-
与其他模式关系:
- 策略模式:结构相似,但目的不同。状态模式的状态是内在的,策略是外在的
- 享元模式:可共享状态对象
- 观察者模式:状态改变时通知观察者
十六、思维总结
状态模式教会我们的不仅是代码组织方式,更是:
- 认识世界的角度:事物的行为由其内在状态决定
- 分解问题的方法:按状态维度切分复杂逻辑
- 代码组织哲学:让数据(状态)拥有行为
- 设计思维转变:从"过程控制"到"对象自治"
最高境界:当你看到复杂的if-else或switch时,第一反应不是"如何优化条件判断",而是"这些条件对应的状态是否应该被建模为对象"。
这种思维方式会让你写出更贴近现实世界、更易维护、更易扩展的代码。状态模式不是银弹,但在状态相关的场景下,它是最优雅的解决方案之一。
状态模式特别适合处理复杂的状态转换逻辑,能够显著提高代码的可读性和可维护性。通过将状态相关的行为封装到独立的状态类中,我们不仅消除了冗长的条件语句,还使得每个状态的行为和转换规则变得更加清晰和易于管理。