C++ 状态模式详解

状态模式(State Pattern)是一种行为设计模式,它允许一个对象在内部状态改变时改变其行为 ,使对象看起来像是改变了其类

核心概念

设计原则

状态模式遵循以下设计原则:

  1. 单一职责原则:将状态相关行为分离到不同类中

  2. 开闭原则:可以新增状态而不修改现有代码

  3. 封装性:状态转换逻辑封装在状态类中

主要优点

  1. 清晰状态转换:将状态转换逻辑组织化

  2. 减少条件语句:消除庞大的条件状态判断

  3. 可扩展性:容易添加新状态和转换

  4. 行为局部化:状态特定行为集中在对应状态类中

模式结构

主要组件

  1. Context(上下文)

    • 维护当前状态的引用

    • 将状态相关请求委托给当前状态对象

  2. State(状态接口)

    • 定义状态接口

    • 封装与Context特定状态相关的行为

  3. ConcreteState(具体状态)

    • 实现状态接口

    • 每个子类实现与Context状态相关的行为

完整代码示例

复制代码
#include <iostream>
#include <memory>
#include <string>

// 前置声明
class State;

// ==================== 上下文类 ====================
class Player {
    std::unique_ptr<State> state_;
    std::string name_;
    
public:
    explicit Player(const std::string& name);
    
    void setState(std::unique_ptr<State> state);
    std::string getName() const;
    
    // 玩家行为
    void play();
    void pause();
    void stop();
    void lock();
    void unlock();
};

// ==================== 状态接口 ====================
class State {
public:
    virtual ~State() = default;
    virtual void play(Player* player) = 0;
    virtual void pause(Player* player) = 0;
    virtual void stop(Player* player) = 0;
    virtual void lock(Player* player) = 0;
    virtual void unlock(Player* player) = 0;
    
protected:
    void changeState(Player* player, std::unique_ptr<State> state) {
        player->setState(std::move(state));
    }
};

// ==================== 具体状态 ====================
class ReadyState : public State {
public:
    void play(Player* player) override;
    void pause(Player* player) override { /* 无效操作 */ }
    void stop(Player* player) override { /* 无效操作 */ }
    void lock(Player* player) override;
    void unlock(Player* player) override { /* 已在解锁状态 */ }
};

class PlayingState : public State {
public:
    void play(Player* player) override { /* 已在播放状态 */ }
    void pause(Player* player) override;
    void stop(Player* player) override;
    void lock(Player* player) override;
    void unlock(Player* player) override { /* 无效操作 */ }
};

class PausedState : public State {
public:
    void play(Player* player) override;
    void pause(Player* player) override { /* 已在暂停状态 */ }
    void stop(Player* player) override;
    void lock(Player* player) override;
    void unlock(Player* player) override { /* 无效操作 */ }
};

class LockedState : public State {
public:
    void play(Player* player) override { /* 锁定状态下不能播放 */ }
    void pause(Player* player) override { /* 锁定状态下不能暂停 */ }
    void stop(Player* player) override { /* 锁定状态下不能停止 */ }
    void lock(Player* player) override { /* 已在锁定状态 */ }
    void unlock(Player* player) override;
};

// ==================== 上下文方法实现 ====================
Player::Player(const std::string& name) : name_(name) {
    state_ = std::make_unique<ReadyState>();
}

void Player::setState(std::unique_ptr<State> state) {
    state_ = std::move(state);
}

std::string Player::getName() const {
    return name_;
}

void Player::play() {
    state_->play(this);
}

void Player::pause() {
    state_->pause(this);
}

void Player::stop() {
    state_->stop(this);
}

void Player::lock() {
    state_->lock(this);
}

void Player::unlock() {
    state_->unlock(this);
}

// ==================== 具体状态方法实现 ====================
void ReadyState::play(Player* player) {
    std::cout << player->getName() << ": 开始播放" << std::endl;
    changeState(player, std::make_unique<PlayingState>());
}

void ReadyState::lock(Player* player) {
    std::cout << player->getName() << ": 锁定播放器" << std::endl;
    changeState(player, std::make_unique<LockedState>());
}

void PlayingState::pause(Player* player) {
    std::cout << player->getName() << ": 暂停播放" << std::endl;
    changeState(player, std::make_unique<PausedState>());
}

void PlayingState::stop(Player* player) {
    std::cout << player->getName() << ": 停止播放" << std::endl;
    changeState(player, std::make_unique<ReadyState>());
}

void PlayingState::lock(Player* player) {
    std::cout << player->getName() << ": 锁定播放器" << std::endl;
    changeState(player, std::make_unique<LockedState>());
}

void PausedState::play(Player* player) {
    std::cout << player->getName() << ": 恢复播放" << std::endl;
    changeState(player, std::make_unique<PlayingState>());
}

void PausedState::stop(Player* player) {
    std::cout << player->getName() << ": 停止播放" << std::endl;
    changeState(player, std::make_unique<ReadyState>());
}

void PausedState::lock(Player* player) {
    std::cout << player->getName() << ": 锁定播放器" << std::endl;
    changeState(player, std::make_unique<LockedState>());
}

void LockedState::unlock(Player* player) {
    std::cout << player->getName() << ": 解锁播放器" << std::endl;
    changeState(player, std::make_unique<ReadyState>());
}

// ==================== 客户端代码 ====================
int main() {
    std::cout << "=== 状态模式演示: 音乐播放器 ===" << std::endl;
    
    Player player("我的播放器");
    
    // 正常流程
    player.play();
    player.pause();
    player.play();
    player.stop();
    
    // 锁定测试
    std::cout << "\n测试锁定功能:" << std::endl;
    player.play();
    player.lock();
    player.play();  // 应该无效
    player.unlock();
    player.play();
    
    // 无效操作测试
    std::cout << "\n测试无效操作:" << std::endl;
    player.stop();
    player.stop();  // 应该无效
    player.pause(); // 应该无效
    
    return 0;
}

模式变体

1. 状态表驱动

复制代码
class StateMachine {
    std::unordered_map<std::string, 
        std::unordered_map<std::string, 
            std::function<void()>>> transitions_;
    std::string currentState_;
    
public:
    void addTransition(const std::string& from, const std::string& event, 
                      const std::string& to, std::function<void()> action) {
        transitions_[from][event] = [this, to, action] {
            action();
            currentState_ = to;
        };
    }
    
    void handleEvent(const std::string& event) {
        auto& stateTransitions = transitions_[currentState_];
        if (stateTransitions.find(event) != stateTransitions.end()) {
            stateTransitions[event]();
        }
    }
};

2. 共享状态对象

复制代码
class SharedState : public State {
    // 可以共享的状态数据
};

class ConcreteStateA : public SharedState {
    // 实现特定行为
};

// 使用时可以共享同一个状态实例
auto sharedState = std::make_shared<ConcreteStateA>();
context1.setState(sharedState);
context2.setState(sharedState);

实际应用场景

  1. 工作流引擎:如订单状态流转

  2. 游戏开发:角色行为状态管理

  3. UI系统:控件不同状态下的行为

  4. 网络协议:协议状态机实现

  5. 硬件控制:设备状态管理

相关推荐
草莓熊Lotso1 小时前
Linux 基础 IO 初步解析:从 C 库函数到系统调用,理解文件操作本质
linux·运维·服务器·c语言·数据库·c++·人工智能
梵刹古音1 小时前
【C语言】 字符数组相关库函数
c语言·开发语言·算法
闻缺陷则喜何志丹1 小时前
P8699 [蓝桥杯 2019 国 B] 排列数|普及+
c++·数学·蓝桥杯·数论·洛谷·数列
D_evil__7 小时前
【Effective Modern C++】第三章 转向现代C++:16. 让const成员函数线程安全
c++
微风中的麦穗7 小时前
【MATLAB】MATLAB R2025a 详细下载安装图文指南:下一代科学计算与工程仿真平台
开发语言·matlab·开发工具·工程仿真·matlab r2025a·matlab r2025·科学计算与工程仿真
2601_949146537 小时前
C语言语音通知API示例代码:基于标准C的语音接口开发与底层调用实践
c语言·开发语言
开源技术7 小时前
Python Pillow 优化,打开和保存速度最快提高14倍
开发语言·python·pillow
学嵌入式的小杨同学7 小时前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
Queenie_Charlie8 小时前
前缀和的前缀和
数据结构·c++·树状数组
码云数智-园园8 小时前
优雅分页:Spring Boot 中 Pageable 参数的自动提取与全局复用实践
状态模式