状态模式(State Pattern)是一种行为设计模式,通过将状态与行为绑定 ,允许对象在内部状态改变时改变其行为 ,使对象看起来好像修改了它的类。核心思想是将对象的状态封装为独立的状态类 ,从而使状态决定行为,行为触发状态转换,通过状态类的切换实现行为的动态变化,而非通过大量if-else
或switch
判断。特别适合状态多、行为依赖状态且状态流转复杂的场景。相比传统的条件判断,状态模式能显著提升代码的可维护性和扩展性。
一、介绍
核心角色
- 环境类(Context):维护当前状态,提供切换状态的接口,并将状态相关的行为委托给当前状态类。
- 抽象状态类(State):定义状态的接口,声明不同状态下的行为方法。
- 具体状态类(Concrete State):实现抽象状态接口,定义特定状态下的具体行为,通常会包含状态转换的逻辑。
优点
- 封装状态逻辑:每个状态的行为和转换规则被封装在独立的状态类中,代码结构清晰,易于理解和维护。
- 消除条件判断 :用状态类的多态替代
if-else
或switch
,避免代码臃肿,提高可读性。 - 易于扩展:新增状态时只需添加新的具体状态类,无需修改环境类和其他状态类(符合开闭原则)。
- 状态转换可控:状态之间的转换规则由状态类统一管理,避免非法状态转换(如"待支付"不能直接转为"已完成")。
适用场景
- 对象行为依赖于状态且状态频繁变化
当一个对象的行为随其状态改变而变化(如订单的支付、发货、确认行为依赖当前状态),且状态之间有明确的流转规则时。 - 避免大量条件判断
当代码中存在大量与状态相关的if-else
或switch
语句(如if (state == 待支付) { ... } else if (state == 已支付) { ... }
),且维护成本高时。 - 状态转换逻辑复杂
当状态转换规则复杂(如某些状态只能从特定状态转换而来),需要将转换逻辑封装在独立类中时。
二、实现
以电商订单的状态流转为例,订单存在"待支付""已支付""已发货""已完成"等状态,不同状态下的行为(如付款、发货、确认收货)不同,且状态之间有固定的流转规则(如"待支付"→"已支付"→"已发货"→"已完成"),适合用状态模式实现。
cpp
#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; // 订单ID
public:
// 构造函数:初始状态为待支付
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
替代裸指针,自动管理状态对象生命周期,避免内存泄漏。 - 状态转换规则外置:将状态转换规则从状态类中剥离,用配置表或策略类管理,支持动态修改流转规则。
- 状态历史记录:添加状态变更日志,支持查询历史状态和回滚操作。
- 事件通知机制:状态变更时通知观察者(结合观察者模式),实现状态变更后的联动操作。
cpp
#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
。 - 业务解耦:状态逻辑、转换规则、联动操作分离,符合单一职责原则。
适用场景扩展
- 复杂工作流系统:如审批流程(需动态调整审批节点和条件)。
- 金融交易系统:如支付状态(待支付→支付中→已支付→退款中→已退款),需严格的状态转换规则和完整日志。
- 设备生命周期管理:如设备状态(生产中→入库→销售→维修→报废),需记录状态变更历史。