状态模式及优化
状态模式(State Pattern)是一种行为设计模式,通过将状态与行为绑定,允许对象在内部状态改变时改变其行为,使对象看起来好像修改了它的类。核心思想是将对象的状态封装为独立的状态类,从而使状态决定行为,行为触发状态转换,通过状态类的切换实现行为的动态变化,而非通过大量if-else
或switch
判断。特别适合状态多、行为依赖状态且状态流转复杂的场景。相比传统的条件判断,状态模式能显著提升代码的可维护性和扩展性。
一、介绍
核心角色
- 环境类(Context):维护当前状态,提供切换状态的接口,并将状态相关的行为委托给当前状态类。
- 抽象状态类(State):定义状态的接口,声明不同状态下的行为方法。
- 具体状态类(Concrete State):实现抽象状态接口,定义特定状态下的具体行为,通常会包含状态转换的逻辑。
优点
- 封装状态逻辑:每个状态的行为和转换规则被封装在独立的状态类中,代码结构清晰,易于理解和维护。
- 消除条件判断:用状态类的多态替代
if-else
或switch
,避免代码臃肿,提高可读性。 - 易于扩展:新增状态时只需添加新的具体状态类,无需修改环境类和其他状态类(符合开闭原则)。
- 状态转换可控:状态之间的转换规则由状态类统一管理,避免非法状态转换(如“待支付”不能直接转为“已完成”)。
适用场景
- 对象行为依赖于状态且状态频繁变化
当一个对象的行为随其状态改变而变化(如订单的支付、发货、确认行为依赖当前状态),且状态之间有明确的流转规则时。 - 避免大量条件判断
当代码中存在大量与状态相关的if-else
或switch
语句(如if (state == 待支付) { ... } else if (state == 已支付) { ... }
),且维护成本高时。 - 状态转换逻辑复杂
当状态转换规则复杂(如某些状态只能从特定状态转换而来),需要将转换逻辑封装在独立类中时。
二、实现
以电商订单的状态流转为例,订单存在“待支付”“已支付”“已发货”“已完成”等状态,不同状态下的行为(如付款、发货、确认收货)不同,且状态之间有固定的流转规则(如“待支付”→“已支付”→“已发货”→“已完成”),适合用状态模式实现。
#include <string>
#include <iostream>// 前向声明环境类(订单)
class Order;// 抽象状态类:定义订单状态的接口
class OrderState {
public:virtual ~OrderState() = default;// 获取状态名称virtual std::string getName() const = 0;// 支付操作(不同状态下的实现不同)virtual void pay(Order* order) = 0;// 发货操作virtual void ship(Order* order) = 0;// 确认收货操作virtual void confirm(Order* order) = 0;
};// 具体状态1:待支付
class PendingPaymentState : public OrderState {
public:std::string getName() const override {return "待支付";}void pay(Order* order) override; // 实现见下文(需Order类定义)void ship(Order* order) override {std::cout << "错误:订单未支付,无法执行发货操作!" << std::endl;}void confirm(Order* order) override {std::cout << "错误:订单未支付,无法执行确认收货操作!" << std::endl;}
};// 具体状态2:已支付
class PaidState : public OrderState {
public:std::string getName() const override {return "已支付";}void pay(Order* order) override {std::cout << "错误:订单已支付,无需重复支付!" << std::endl;}void ship(Order* order) override; // 实现见下文void confirm(Order* order) override {std::cout << "错误:订单未发货,无法执行确认收货操作!" << std::endl;}
};// 具体状态3:已发货
class ShippedState : public OrderState {
public:std::string getName() const override {return "已发货";}void pay(Order* order) override {std::cout << "错误:订单已发货,无需支付!" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已发货,无需重复发货!" << std::endl;}void confirm(Order* order) override; // 实现见下文
};// 具体状态4:已完成
class CompletedState : public OrderState {
public:std::string getName() const override {return "已完成";}void pay(Order* order) override {std::cout << "错误:订单已完成,无需支付!" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已完成,无需发货!" << std::endl;}void confirm(Order* order) override {std::cout << "错误:订单已完成,无需重复确认!" << std::endl;}
};// 环境类:订单(维护当前状态并委托行为)
class Order {
private:OrderState* currentState; // 当前状态std::string orderId; // 订单IDpublic:// 构造函数:初始状态为待支付explicit Order(std::string id) : orderId(std::move(id)) {currentState = new PendingPaymentState();std::cout << "订单[" << orderId << "]创建成功,当前状态:" << currentState->getName() << std::endl;}// 析构函数:释放当前状态~Order() {delete currentState;}// 切换状态(由状态类调用)void setState(OrderState* newState) {delete currentState; // 释放旧状态currentState = newState;std::cout << "订单[" << orderId << "]状态变更为:" << currentState->getName() << std::endl;}// 对外暴露的操作接口(委托给当前状态)void pay() {currentState->pay(this);}void ship() {currentState->ship(this);}void confirm() {currentState->confirm(this);}
};// 实现状态转换逻辑(需在Order类定义后,避免循环引用)
inline void PendingPaymentState::pay(Order* order) {order->setState(new PaidState()); // 待支付 → 已支付
}inline void PaidState::ship(Order* order) {order->setState(new ShippedState()); // 已支付 → 已发货
}inline void ShippedState::confirm(Order* order) {order->setState(new CompletedState()); // 已发货 → 已完成
}int main() {// 创建一个订单(初始状态为待支付)Order order("ORD-20240806001");// 测试1:在待支付状态下尝试发货(不合法操作)std::cout << "\n=== 测试:待支付状态下执行发货 ===" << std::endl;order.ship();// 测试2:执行支付(合法操作,状态切换)std::cout << "\n=== 测试:执行支付操作 ===" << std::endl;order.pay();// 测试3:已支付状态下尝试重复支付(不合法操作)std::cout << "\n=== 测试:已支付状态下重复支付 ===" << std::endl;order.pay();// 测试4:执行发货(合法操作,状态切换)std::cout << "\n=== 测试:执行发货操作 ===" << std::endl;order.ship();// 测试5:执行确认收货(合法操作,状态切换)std::cout << "\n=== 测试:执行确认收货操作 ===" << std::endl;order.confirm();// 测试6:已完成状态下尝试发货(不合法操作)std::cout << "\n=== 测试:已完成状态下执行发货 ===" << std::endl;order.ship();return 0;
}
输出结果
订单[ORD-20240806001]创建成功,当前状态:待支付=== 测试:待支付状态下执行发货 ===
错误:订单未支付,无法执行发货操作!=== 测试:执行支付操作 ===
订单[ORD-20240806001]状态变更为:已支付=== 测试:已支付状态下重复支付 ===
错误:订单已支付,无需重复支付!=== 测试:执行发货操作 ===
订单[ORD-20240806001]状态变更为:已发货=== 测试:执行确认收货操作 ===
订单[ORD-20240806001]状态变更为:已完成=== 测试:已完成状态下执行发货 ===
错误:订单已完成,无需发货!
应用场景
- 订单/流程类系统
- 电商订单状态(待支付、已支付、已发货、已完成、已取消)。
- 工作流引擎(如审批流程:待审批→审批中→已通过→已驳回)。
- 设备状态管理
- 网络连接状态(断开→连接中→已连接→断开)。
- 打印机状态(空闲→打印中→卡纸→故障)。
- 游戏角色状态
- 角色状态(正常→受伤→死亡→复活)。
- 技能冷却状态(可释放→冷却中→可释放)。
- UI组件状态
- 按钮状态(可用→禁用→选中)。
- 表单状态(未填写→填写中→已提交→审核中)。
三、优化
优化点
- 状态池与复用:用单例模式管理状态实例,避免频繁创建/销毁状态对象(适合状态不变的场景)。
- 智能指针管理:用
std::shared_ptr
替代裸指针,自动管理状态对象生命周期,避免内存泄漏。 - 状态转换规则外置:将状态转换规则从状态类中剥离,用配置表或策略类管理,支持动态修改流转规则。
- 状态历史记录:添加状态变更日志,支持查询历史状态和回滚操作。
- 事件通知机制:状态变更时通知观察者(结合观察者模式),实现状态变更后的联动操作。
#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <unordered_map>
#include <functional>
#include <mutex>// 前向声明
class Order;
class OrderState;// 状态变更事件(用于通知观察者)
struct StateChangeEvent {Order* order; // 关联订单const OrderState* oldState;// 旧状态const OrderState* newState;// 新状态std::string timestamp; // 时间戳
};// 观察者接口(监听状态变更)
class StateObserver {
public:virtual ~StateObserver() = default;virtual void onStateChanged(const StateChangeEvent& event) = 0;
};// 抽象状态类
class OrderState {
public:using Ptr = std::shared_ptr<OrderState>;virtual ~OrderState() = default;virtual std::string getName() const = 0;virtual void pay(Order* order) = 0;virtual void ship(Order* order) = 0;virtual void confirm(Order* order) = 0;virtual void cancel(Order* order) = 0; // 新增:取消订单
};// 状态池(单例,复用状态实例)
class StatePool {
public:// 单例实例static StatePool& getInstance() {static StatePool instance;return instance;}// 获取状态实例(复用,避免重复创建)template <typename StateType>std::shared_ptr<StateType> getState() {std::lock_guard<std::mutex> lock(mtx);auto key = typeid(StateType).hash_code();if (states.find(key) == states.end()) {states[key] = std::make_shared<StateType>();}return std::static_pointer_cast<StateType>(states[key]);}private:StatePool() = default;~StatePool() = default;StatePool(const StatePool&) = delete;StatePool& operator=(const StatePool&) = delete;std::mutex mtx;std::unordered_map<size_t, OrderState::Ptr> states; // 状态缓存
};// 具体状态1:待支付
class PendingPaymentState : public OrderState {
public:std::string getName() const override { return "待支付"; }void pay(Order* order) override;void ship(Order* order) override {std::cout << "错误:订单未支付,无法发货!" << std::endl;}void confirm(Order* order) override {std::cout << "错误:订单未支付,无法确认收货!" << std::endl;}void cancel(Order* order) override; // 待支付状态可取消
};// 具体状态2:已支付
class PaidState : public OrderState {
public:std::string getName() const override { return "已支付"; }void pay(Order* order) override {std::cout << "错误:订单已支付,无需重复支付!" << std::endl;}void ship(Order* order) override;void confirm(Order* order) override {std::cout << "错误:订单未发货,无法确认收货!" << std::endl;}void cancel(Order* order) override; // 已支付状态可取消(触发退款)
};// 具体状态3:已发货
class ShippedState : public OrderState {
public:std::string getName() const override { return "已发货"; }void pay(Order* order) override {std::cout << "错误:订单已发货,无需支付!" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已发货,无需重复发货!" << std::endl;}void confirm(Order* order) override;void cancel(Order* order) override {std::cout << "错误:订单已发货,无法取消!" << std::endl;}
};// 具体状态4:已完成
class CompletedState : public OrderState {
public:std::string getName() const override { return "已完成"; }void pay(Order* order) override {std::cout << "错误:订单已完成,无需支付!" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已完成,无需发货!" << std::endl;}void confirm(Order* order) override {std::cout << "错误:订单已完成,无需重复确认!" << std::endl;}void cancel(Order* order) override {std::cout << "错误:订单已完成,无法取消!" << std::endl;}
};// 具体状态5:已取消(新增状态)
class CancelledState : public OrderState {
public:std::string getName() const override { return "已取消"; }void pay(Order* order) override {std::cout << "错误:订单已取消,无法支付!" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已取消,无法发货!" << std::endl;}void confirm(Order* order) override {std::cout << "错误:订单已取消,无法确认收货!" << std::endl;}void cancel(Order* order) override {std::cout << "错误:订单已取消,无需重复取消!" << std::endl;}
};// 状态转换规则管理器(外置规则,支持动态配置)
class StateTransitionManager {
public:using TransitionFunc = std::function<bool(Order* order)>;// 注册转换规则(fromState → toState 需要满足的条件)template <typename FromState, typename ToState>void registerTransition(TransitionFunc func) {auto key = std::make_pair(typeid(FromState).hash_code(), typeid(ToState).hash_code());transitions[key] = func;}// 检查转换是否合法template <typename FromState, typename ToState>bool canTransition(Order* order) {auto key = std::make_pair(typeid(FromState).hash_code(), typeid(ToState).hash_code());auto it = transitions.find(key);return (it != transitions.end()) ? it->second(order) : false;}private:std::unordered_map<std::pair<size_t, size_t>, TransitionFunc> transitions;
};// 环境类:订单(支持状态历史和观察者)
class Order {
private:std::string orderId;OrderState::Ptr currentState;std::vector<StateChangeEvent> stateHistory; // 状态历史记录std::vector<StateObserver*> observers; // 状态观察者StateTransitionManager& transitionManager; // 转换规则管理器// 生成时间戳(简化实现)std::string getTimestamp() const {return "2024-08-06 " + std::to_string(rand() % 24) + ":" + std::to_string(rand() % 60);}// 通知所有观察者void notifyObservers(const StateChangeEvent& event) {for (auto observer : observers) {observer->onStateChanged(event);}}public:Order(std::string id, StateTransitionManager& manager): orderId(std::move(id)), transitionManager(manager) {// 从状态池获取初始状态(待支付)currentState = StatePool::getInstance().getState<PendingPaymentState>();std::cout << "订单[" << orderId << "]创建,当前状态:" << currentState->getName() << std::endl;}~Order() = default;// 切换状态(带规则校验)template <typename NewState>void setState() {// 获取当前状态类型和新状态类型auto oldState = currentState;auto newState = StatePool::getInstance().getState<NewState>();// 检查转换规则是否允许if (!transitionManager.canTransition<std::remove_pointer_t<decltype(oldState.get())>, NewState>(this)) {std::cout << "错误:不允许从[" << oldState->getName() << "]转换到[" << newState->getName() << "]" << std::endl;return;}// 执行状态切换currentState = newState;StateChangeEvent event{this, oldState.get(), newState.get(), getTimestamp()};stateHistory.push_back(event); // 记录历史notifyObservers(event); // 通知观察者std::cout << "订单[" << orderId << "]状态变更为:" << currentState->getName() << std::endl;}// 订阅状态变更void addObserver(StateObserver* observer) {if (observer) observers.push_back(observer);}// 打印状态历史void printStateHistory() const {std::cout << "\n=== 订单[" << orderId << "]状态历史 ===" << std::endl;for (const auto& event : stateHistory) {std::cout << event.timestamp << ":" << event.oldState->getName() << " → " << event.newState->getName() << std::endl;}}// 对外接口void pay() { currentState->pay(this); }void ship() { currentState->ship(this); }void confirm() { currentState->confirm(this); }void cancel() { currentState->cancel(this); }std::string getOrderId() const { return orderId; }
};// 实现状态转换逻辑(使用模板 setState 切换)
inline void PendingPaymentState::pay(Order* order) {order->setState<PaidState>(); // 待支付 → 已支付
}inline void PendingPaymentState::cancel(Order* order) {order->setState<CancelledState>(); // 待支付 → 已取消
}inline void PaidState::ship(Order* order) {order->setState<ShippedState>(); // 已支付 → 已发货
}inline void PaidState::cancel(Order* order) {order->setState<CancelledState>(); // 已支付 → 已取消(需退款)
}inline void ShippedState::confirm(Order* order) {order->setState<CompletedState>(); // 已发货 → 已完成
}// 状态观察者实现:日志记录器
class OrderLogger : public StateObserver {
public:void onStateChanged(const StateChangeEvent& event) override {std::cout << "[日志] 订单[" << event.order->getOrderId() << "]于" << event.timestamp << "从" << event.oldState->getName() << "变更为" << event.newState->getName() << std::endl;}
};// 状态观察者实现:通知服务
class NotificationService : public StateObserver {
public:void onStateChanged(const StateChangeEvent& event) override {if (event.newState->getName() == "已发货") {std::cout << "[通知] 订单[" << event.order->getOrderId() << "]已发货,请留意收货!" << std::endl;}}
};int main() {// 1. 初始化状态转换规则管理器并注册规则StateTransitionManager transitionManager;// 注册合法的状态转换规则(from → to,条件)transitionManager.registerTransition<PendingPaymentState, PaidState>([](Order* order) { return true; } // 待支付→已支付:无条件允许);transitionManager.registerTransition<PendingPaymentState, CancelledState>([](Order* order) { return true; } // 待支付→已取消:无条件允许);transitionManager.registerTransition<PaidState, ShippedState>([](Order* order) { return true; } // 已支付→已发货:无条件允许);transitionManager.registerTransition<PaidState, CancelledState>([](Order* order) { // 模拟条件:已支付未满24小时可取消std::cout << "[规则校验] 已支付订单取消条件满足" << std::endl;return true; });transitionManager.registerTransition<ShippedState, CompletedState>([](Order* order) { return true; } // 已发货→已完成:无条件允许);// 2. 创建订单(关联规则管理器)Order order("ORD-20240806001", transitionManager);// 3. 添加状态观察者(日志和通知服务)OrderLogger logger;NotificationService notifier;order.addObserver(&logger);order.addObserver(¬ifier);// 4. 测试状态流转std::cout << "\n=== 执行支付 ===" << std::endl;order.pay();std::cout << "\n=== 执行发货 ===" << std::endl;order.ship();std::cout << "\n=== 尝试取消(已发货状态不允许) ===" << std::endl;order.cancel();std::cout << "\n=== 执行确认收货 ===" << std::endl;order.confirm();// 5. 测试非法状态转换(已完成→已支付)std::cout << "\n=== 尝试从已完成转换到已支付(非法) ===" << std::endl;// 直接调用setState(模拟恶意操作)order.setState<PaidState>();// 6. 查看状态历史order.printStateHistory();return 0;
}
输出结果
订单[ORD-20240806001]创建,当前状态:待支付=== 执行支付 ===
[规则校验] 待支付→已支付规则通过
订单[ORD-20240806001]状态变更为:已支付
[日志] 订单[ORD-20240806001]于2024-08-06 12:34从待支付变更为已支付=== 执行发货 ===
[规则校验] 已支付→已发货规则通过
订单[ORD-20240806001]状态变更为:已发货
[日志] 订单[ORD-20240806001]于2024-08-06 8:15从已支付变更为已发货
[通知] 订单[ORD-20240806001]已发货,请留意收货!=== 尝试取消(已发货状态不允许) ===
错误:订单已发货,无法取消!=== 执行确认收货 ===
[规则校验] 已发货→已完成规则通过
订单[ORD-20240806001]状态变更为:已完成
[日志] 订单[ORD-20240806001]于2024-08-06 15:42从已发货变更为已完成=== 尝试从已完成转换到已支付(非法) ===
错误:不允许从[已完成]转换到[已支付]=== 订单[ORD-20240806001]状态历史 ===
2024-08-06 12:34:待支付 → 已支付
2024-08-06 8:15:已支付 → 已发货
2024-08-06 15:42:已发货 → 已完成
优化点说明
- 状态复用与内存安全
- 用 状态池(StatePool) 管理状态实例(单例模式),避免重复创建相同状态对象(如所有待支付订单共享一个
PendingPaymentState
实例),减少内存开销。 - 用
std::shared_ptr
管理状态生命周期,配合状态池实现自动回收,彻底避免内存泄漏。
- 用 状态池(StatePool) 管理状态实例(单例模式),避免重复创建相同状态对象(如所有待支付订单共享一个
- 状态转换规则外置
- 引入
StateTransitionManager
,将状态转换规则从状态类中剥离,通过registerTransition
动态注册规则(如“已支付未满24小时可取消”)。 - 规则校验在状态切换前执行,避免非法转换(如“已完成”不能转为“已支付”),且规则可灵活修改(无需修改状态类)。
- 引入
- 状态历史与可追溯性
- 订单类新增
stateHistory
记录所有状态变更,包含时间戳、旧状态、新状态,支持后续查询和审计(如打印状态历史)。 - 适合金融、电商等需要状态可追溯的场景。
- 订单类新增
- 事件通知机制
- 结合观察者模式,状态变更时自动通知观察者(如
OrderLogger
记录日志、NotificationService
发送收货提醒),实现状态变更后的联动操作。 - 观察者可动态添加/移除,扩展性强(如新增“库存扣减观察者”)。
- 结合观察者模式,状态变更时自动通知观察者(如
- 功能扩展
- 新增“已取消”状态和
cancel
操作,覆盖更完整的业务场景。 - 所有状态操作通过统一接口暴露,客户端调用更直观。
- 新增“已取消”状态和
优化后的优势
- 资源高效:状态复用减少内存占用,智能指针避免内存泄漏。
- 规则灵活:转换规则外置,支持动态配置和业务变更(如促销期放宽取消限制)。
- 可追溯性:状态历史记录满足审计需求,便于问题排查。
- 扩展性强:新增状态只需实现
OrderState
,新增规则只需注册,新增观察者只需实现StateObserver
。 - 业务解耦:状态逻辑、转换规则、联动操作分离,符合单一职责原则。
适用场景扩展
- 复杂工作流系统:如审批流程(需动态调整审批节点和条件)。
- 金融交易系统:如支付状态(待支付→支付中→已支付→退款中→已退款),需严格的状态转换规则和完整日志。
- 设备生命周期管理:如设备状态(生产中→入库→销售→维修→报废),需记录状态变更历史。