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

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

一、核心思想与角色

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

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

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

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

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

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

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

cpp 复制代码
#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); }

    // 友元声明:允许状态类调用setState
    friend 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. 明确状态流转规则:通过文档或枚举定义清晰的状态转换规则,避免状态逻辑混乱。

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

相关推荐
会开花的二叉树3 小时前
分布式文件存储 RPC 服务实现
c++·分布式·网络协议·rpc
abcd_zjq3 小时前
VS2026+QT6.9+opencv图像增强(多帧平均降噪)(CLAHE对比度增强)(边缘增强)(图像超分辨率)
c++·图像处理·qt·opencv·visual studio
Algebraaaaa4 小时前
Qt中的字符串宏 | 编译期检查和运行期检查 | Qt信号与槽connect写法
开发语言·c++·qt
Predestination王瀞潞9 小时前
IO操作(Num22)
开发语言·c++
宋恩淇要努力11 小时前
C++继承
开发语言·c++
江公望13 小时前
Qt qmlRegisterSingletonType()函数浅谈
c++·qt
rongqing201914 小时前
Google 智能体设计模式:人机协同(HITL)
设计模式
逆小舟14 小时前
【C/C++】指针
c语言·c++·笔记·学习
江公望14 小时前
Qt QtConcurrent使用入门浅解
c++·qt·qml