当前位置: 首页 > news >正文

C++设计模式之行为型模式:状态模式(State)

状态模式(State)是行为型设计模式的一种,它允许对象在内部状态改变时改变其行为,使对象看起来好像修改了它的类。这种模式将状态封装为独立的类,并将对象的行为委托给当前状态,从而实现状态与行为的解耦。

一、核心思想与角色

状态模式的核心是“状态决定行为”,通过将不同状态下的行为封装到对应的状态类中,使对象在切换状态时自动改变行为。其核心角色如下:

角色名称核心职责
环境类(Context)维护一个当前状态的引用,提供切换状态的接口,将行为委托给当前状态。
抽象状态(State)定义所有具体状态的公共接口,声明环境类中依赖状态的方法。
具体状态(ConcreteState)实现抽象状态接口,定义特定状态下环境类的行为,可能包含状态转换的逻辑。

核心思想:将对象在不同状态下的行为分离到不同的状态类中,环境类通过切换当前状态对象来改变自身行为,避免使用大量条件判断(if-elseswitch-case)。

二、实现示例(订单状态流转)

假设我们需要设计一个电商订单系统,订单有多种状态(待支付、已支付、已发货、已完成、已取消),不同状态下支持的操作不同:

  • 待支付:可支付、可取消
  • 已支付:可发货、可退款(取消)
  • 已发货:可确认收货
  • 已完成:可评价(简化)
  • 已取消:无有效操作

使用状态模式可清晰管理状态流转和对应行为:

#include <iostream>
#include <string>// 前向声明环境类
class Order;// 2. 抽象状态:订单状态
class OrderState {
public:// 纯虚方法:各种状态下的操作virtual void pay(Order* order) = 0;         // 支付virtual void ship(Order* order) = 0;        // 发货virtual void confirmReceipt(Order* order) = 0; // 确认收货virtual void cancel(Order* order) = 0;      // 取消订单virtual std::string getStateName() = 0;     // 获取状态名称virtual ~OrderState() = default;
};// 1. 环境类:订单
class Order {
private:OrderState* currentState; // 当前状态std::string orderId;      // 订单ID// 切换状态(私有,仅状态类可调用)void setState(OrderState* newState) {currentState = newState;std::cout << "订单[" << orderId << "]状态变更为:" << currentState->getStateName() << std::endl;}public:Order(const std::string& id);~Order();// 订单操作(委托给当前状态)void pay() { currentState->pay(this); }void ship() { currentState->ship(this); }void confirmReceipt() { currentState->confirmReceipt(this); }void cancel() { currentState->cancel(this); }// 友元声明:允许状态类调用setStatefriend class PendingPaymentState;friend class PaidState;friend class ShippedState;friend class CompletedState;friend class CancelledState;
};// 3. 具体状态1:待支付
class PendingPaymentState : public OrderState {
public:void pay(Order* order) override;void ship(Order* order) override {std::cout << "错误:订单未支付,无法发货" << std::endl;}void confirmReceipt(Order* order) override {std::cout << "错误:订单未支付,无法确认收货" << std::endl;}void cancel(Order* order) override;std::string getStateName() override { return "待支付"; }// 单例模式:减少状态对象创建(状态无内部状态时适用)static PendingPaymentState* getInstance() {static PendingPaymentState instance;return &instance;}
};// 3. 具体状态2:已支付
class PaidState : public OrderState {
public:void pay(Order* order) override {std::cout << "错误:订单已支付,无需重复支付" << std::endl;}void ship(Order* order) override;void confirmReceipt(Order* order) override {std::cout << "错误:订单未发货,无法确认收货" << std::endl;}void cancel(Order* order) override;std::string getStateName() override { return "已支付"; }static PaidState* getInstance() {static PaidState instance;return &instance;}
};// 3. 具体状态3:已发货
class ShippedState : public OrderState {
public:void pay(Order* order) override {std::cout << "错误:订单已发货,无需支付" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已发货,无法重复发货" << std::endl;}void confirmReceipt(Order* order) override;void cancel(Order* order) override {std::cout << "错误:订单已发货,无法取消" << std::endl;}std::string getStateName() override { return "已发货"; }static ShippedState* getInstance() {static ShippedState instance;return &instance;}
};// 3. 具体状态4:已完成
class CompletedState : public OrderState {
public:void pay(Order* order) override {std::cout << "错误:订单已完成,无需支付" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已完成,无需发货" << std::endl;}void confirmReceipt(Order* order) override {std::cout << "错误:订单已完成,无需重复确认" << std::endl;}void cancel(Order* order) override {std::cout << "错误:订单已完成,无法取消" << std::endl;}std::string getStateName() override { return "已完成"; }static CompletedState* getInstance() {static CompletedState instance;return &instance;}
};// 3. 具体状态5:已取消
class CancelledState : public OrderState {
public:void pay(Order* order) override {std::cout << "错误:订单已取消,无法支付" << std::endl;}void ship(Order* order) override {std::cout << "错误:订单已取消,无法发货" << std::endl;}void confirmReceipt(Order* order) override {std::cout << "错误:订单已取消,无法确认收货" << std::endl;}void cancel(Order* order) override {std::cout << "错误:订单已取消,无需重复取消" << std::endl;}std::string getStateName() override { return "已取消"; }static CancelledState* getInstance() {static CancelledState instance;return &instance;}
};// 实现Order类的构造和析构
Order::Order(const std::string& id) : orderId(id) {// 初始状态为待支付currentState = PendingPaymentState::getInstance();std::cout << "创建订单[" << orderId << "],初始状态:" << currentState->getStateName() << std::endl;
}Order::~Order() {std::cout << "订单[" << orderId << "]处理结束" << std::endl;
}// 实现PendingPaymentState的状态转换
void PendingPaymentState::pay(Order* order) {// 待支付 → 已支付order->setState(PaidState::getInstance());
}void PendingPaymentState::cancel(Order* order) {// 待支付 → 已取消order->setState(CancelledState::getInstance());
}// 实现PaidState的状态转换
void PaidState::ship(Order* order) {// 已支付 → 已发货order->setState(ShippedState::getInstance());
}void PaidState::cancel(Order* order) {// 已支付 → 已取消(退款)order->setState(CancelledState::getInstance());
}// 实现ShippedState的状态转换
void ShippedState::confirmReceipt(Order* order) {// 已发货 → 已完成order->setState(CompletedState::getInstance());
}// 客户端代码:测试订单状态流转
int main() {// 创建订单(初始状态:待支付)Order* order = new Order("ORD-20230901-12345");// 执行一系列操作,触发状态转换std::cout << "\n=== 尝试支付 ===" << std::endl;order->pay();std::cout << "\n=== 尝试发货 ===" << std::endl;order->ship();std::cout << "\n=== 尝试确认收货 ===" << std::endl;order->confirmReceipt();std::cout << "\n=== 尝试再次支付(无效操作) ===" << std::endl;order->pay();// 另一个订单测试取消流程std::cout << "\n\n=== 测试取消流程 ===" << std::endl;Order* order2 = new Order("ORD-20230901-67890");std::cout << "\n=== 直接取消 ===" << std::endl;order2->cancel();std::cout << "\n=== 尝试支付(已取消状态) ===" << std::endl;order2->pay();// 释放资源delete order;delete order2;return 0;
}

三、代码解析

  1. 抽象状态(OrderState)
    定义了订单的所有可能操作(pay()ship()等)和获取状态名称的接口,是所有具体状态的基类。

  2. 具体状态
    每个状态类(如PendingPaymentStatePaidState)实现OrderState接口,定义该状态下允许的操作和状态转换逻辑:

    • 允许的操作(如待支付状态的pay())会触发状态转换(调用order->setState()切换到新状态)。
    • 不允许的操作(如待支付状态的ship())会输出错误提示。
    • 使用单例模式(getInstance())减少状态对象的创建(状态无内部数据时适用)。
  3. 环境类(Order)

    • 维护当前状态(currentState),将所有操作委托给当前状态对象(如pay()实际调用currentState->pay(this))。
    • 提供setState()方法供状态类切换状态(通过友元声明允许状态类访问)。
    • 包含订单的基本信息(如orderId),是状态操作的上下文。
  4. 客户端使用
    客户端创建订单后,直接调用订单的操作方法(pay()ship()等),无需关心当前状态,状态转换由状态类内部自动处理。

四、核心优势与适用场景

优势
  1. 消除条件判断:将状态相关的条件分支逻辑分散到不同状态类中,避免冗长的if-elseswitch-case,代码更清晰。
  2. 状态与行为分离:每个状态的行为封装在对应的状态类中,符合单一职责原则,便于维护和扩展。
  3. 简化状态转换:状态转换逻辑集中在状态类中,而非环境类,使状态流转更清晰。
  4. 易于扩展新状态:新增状态只需添加新的状态类,无需修改现有代码(符合开闭原则)。
适用场景
  1. 对象行为依赖于状态:如订单状态、游戏角色状态(存活/死亡/中毒)、设备状态(运行/暂停/停止)。
  2. 存在复杂状态转换:当对象有多个状态,且状态间转换规则复杂时。
  3. 需要避免大量条件判断:当使用条件语句管理状态导致代码难以维护时。

五、与其他模式的区别

模式核心差异点
状态模式对象行为随状态改变而改变,状态间可相互转换,强调“状态驱动行为”。
策略模式封装不同算法,算法间无依赖,客户端主动选择算法,强调“算法替换”。
享元模式共享细粒度对象,关注对象复用,与状态管理无关。
状态模式 vs 职责链状态模式中状态转换由当前状态决定,职责链中请求由第一个能处理的对象处理。

六、实践建议

  1. 状态类使用单例:当状态无内部数据时,使用单例模式减少对象创建(如示例),节省资源。
  2. 状态转换集中管理:状态转换逻辑可集中在环境类或专门的状态管理器中,避免状态类间过度耦合。
  3. 限制状态数量:状态过多会导致状态类数量激增,此时可考虑结合其他模式(如享元模式)优化。
  4. 明确状态流转规则:通过文档或枚举定义清晰的状态转换规则,避免状态逻辑混乱。

状态模式的核心价值在于“将状态驱动的行为模块化”,它通过分离不同状态下的行为,使系统更易于理解、扩展和维护。在需要管理复杂状态转换的场景中,状态模式能有效替代冗长的条件判断,提升代码质量。

http://www.dtcms.com/a/469551.html

相关文章:

  • 免费自助建站网站一览网络营销推广方法有哪几种
  • 小伙做网站浦东做网站公司
  • Java对象与字符串相互转化的方式
  • 纪检网站建设计划wordpress 防止被黑
  • MXIC旺宏NOR Flash实现微秒级光形切换
  • 5、docker存储卷
  • docker搭建高性能运营级流媒体服务框架ZLMediaKit——筑梦之路
  • 完美迁移:将 nvm 和 npm 完全安装到 Windows D 盘
  • 从零到一:用 Vue 打造一个零依赖、插件化的 JS 库
  • 创建好git项目仓库后如何将本地项目传上去
  • wordpress图片主题模板下载南山网站优化
  • 做外贸大大小小的网站有哪些新手如何做外贸生意
  • langchain4j+SpringBoot+DashScope(灵积)整合
  • MATLAB实现直流电法和大地电磁法的一维正演计算
  • IBM 开源轻量级多模态文档理解模型 Granite-Docling:258M 参数,精准还原 PDF、截图中的公式、表格与代码
  • Python PDF文档加密与保护:确保你的文件安全
  • 【Conda】Conda虚拟环境配置系统环境变量,Jupter可使用
  • 网站网页和网址的关系湘潭seo
  • 对象集合里的id用逗号拼装几种方式
  • 框架--MybatisPlus
  • Coze源码分析-资源库-编辑数据库-前端源码-核心逻辑与接口
  • TikTok SDE OA 2025 真题解析与秋招趋势
  • idea 中 mapper.xml黄线警告怎么去掉
  • NXP - MDK460的调试设置
  • 15.UE-游戏逆向-DumpUE struct
  • 百度统计api兰州企业网站排名优化
  • 网站右下角悬浮窗口js代码 兼容各浏览器页面置换算法课程设计
  • NeurIPS 2025 | 华中科大小米等提出语义提示扩散Transformer,实现精准深度估计新范式!
  • Ansible-playbook剧本
  • Mata Summon - Transform text prompts or photos into dynamic.