C++状态模式解析与实战应用 📅 发布时间:2026/9/12 11:49:22 👁 浏览次数: 1. 状态模式基础解析状态模式是行为设计模式中的经典实现它允许对象在内部状态改变时改变其行为。这种模式特别适合处理那些在不同状态下表现出完全不同行为的对象避免了大量条件判断语句的堆积。1.1 状态模式的核心组成状态模式通常包含三个关键组件Context上下文定义客户端需要的接口维护一个具体状态类的实例这个实例定义当前状态State状态接口定义一个接口用于封装与Context的特定状态相关的行为ConcreteState具体状态实现State接口的具体类每个类对应Context的一个具体状态在C实现中我们通常会看到这样的类关系class Context; // 前向声明 class State { public: virtual ~State() default; virtual void handle(Context* context) 0; }; class ConcreteStateA : public State { public: void handle(Context* context) override; }; class ConcreteStateB : public State { public: void handle(Context* context) override; }; class Context { private: State* currentState; public: Context(State* initialState) : currentState(initialState) {} void setState(State* newState) { delete currentState; currentState newState; } void request() { currentState-handle(this); } };1.2 状态模式解决的问题状态模式主要解决两种常见问题消除庞大的条件语句当对象的行为取决于它的状态并且它必须在运行时根据状态改变行为时状态模式可以避免大量的条件判断状态转换的封装将与特定状态相关的行为局部化并且将状态转换逻辑集中管理提示当你的代码中出现大量检查对象状态的if-else或switch-case语句时就应该考虑使用状态模式了。2. C状态模式实现详解2.1 基础实现框架让我们从一个简单的交通灯状态转换示例开始#include iostream #include memory // 前向声明 class TrafficLight; // 状态接口 class TrafficLightState { public: virtual ~TrafficLightState() default; virtual void change(TrafficLight* light) 0; virtual void reportState() const 0; }; // 具体状态红灯 class RedLight : public TrafficLightState { public: void change(TrafficLight* light) override; void reportState() const override { std::cout 当前状态红灯 std::endl; } }; // 具体状态绿灯 class GreenLight : public TrafficLightState { public: void change(TrafficLight* light) override; void reportState() const override { std::cout 当前状态绿灯 std::endl; } }; // 具体状态黄灯 class YellowLight : public TrafficLightState { public: void change(TrafficLight* light) override; void reportState() const override { std::cout 当前状态黄灯 std::endl; } }; // 上下文类交通灯 class TrafficLight { private: std::unique_ptrTrafficLightState currentState; public: TrafficLight() : currentState(std::make_uniqueRedLight()) {} void setState(std::unique_ptrTrafficLightState newState) { currentState std::move(newState); } void change() { currentState-change(this); } void report() const { currentState-reportState(); } }; // 状态转换实现 void RedLight::change(TrafficLight* light) { std::cout 红灯 - 绿灯 std::endl; light-setState(std::make_uniqueGreenLight()); } void GreenLight::change(TrafficLight* light) { std::cout 绿灯 - 黄灯 std::endl; light-setState(std::make_uniqueYellowLight()); } void YellowLight::change(TrafficLight* light) { std::cout 黄灯 - 红灯 std::endl; light-setState(std::make_uniqueRedLight()); } int main() { TrafficLight light; for (int i 0; i 6; i) { light.report(); light.change(); } return 0; }2.2 智能指针管理状态在现代C中我们更推荐使用智能指针来管理状态对象class Context { private: std::unique_ptrState currentState; public: Context(std::unique_ptrState initialState) : currentState(std::move(initialState)) {} void transitionTo(std::unique_ptrState newState) { currentState std::move(newState); } void request() { currentState-handle(this); } };使用智能指针的好处自动内存管理避免内存泄漏明确所有权语义异常安全2.3 状态转换的几种方式状态转换可以有以下几种实现方式由Context决定下一状态void Context::request() { currentState-handle(this); // Context决定下一状态 if (someCondition) { transitionTo(std::make_uniqueStateA()); } else { transitionTo(std::make_uniqueStateB()); } }由当前状态决定下一状态void ConcreteStateA::handle(Context* context) { // 处理状态A的逻辑 context-transitionTo(std::make_uniqueStateB()); }使用状态表std::unordered_mapStateType, std::functionstd::unique_ptrState() stateFactories { {StateType::A, [](){ return std::make_uniqueStateA(); }}, {StateType::B, [](){ return std::make_uniqueStateB(); }} }; void Context::transitionTo(StateType type) { currentState stateFactories[type](); }3. 状态模式高级应用3.1 状态模式与有限状态机(FSM)状态模式是实现有限状态机的理想选择。下面是一个简单的门状态机实现class Door { public: enum class State { OPEN, CLOSED, LOCKED }; Door() : state(State::CLOSED) {} void open() { switch(state) { case State::CLOSED: state State::OPEN; break; case State::OPEN: std::cout 门已经是开着的 std::endl; break; case State::LOCKED: std::cout 门被锁着无法打开 std::endl; break; } } // 其他方法... private: State state; };使用状态模式重构后class Door; class DoorState { public: virtual ~DoorState() default; virtual void open(Door* door) 0; virtual void close(Door* door) 0; virtual void lock(Door* door) 0; virtual void unlock(Door* door) 0; }; class OpenState : public DoorState { public: void open(Door* door) override { std::cout 门已经是开着的 std::endl; } void close(Door* door) override; void lock(Door* door) override { std::cout 开着的门不能上锁 std::endl; } void unlock(Door* door) override { std::cout 门已经是解锁状态 std::endl; } }; // 其他状态类实现类似... class Door { private: std::unique_ptrDoorState state; public: Door() : state(std::make_uniqueClosedState()) {} void setState(std::unique_ptrDoorState newState) { state std::move(newState); } void open() { state-open(this); } void close() { state-close(this); } void lock() { state-lock(this); } void unlock() { state-unlock(this); } };3.2 状态模式与游戏开发在游戏开发中状态模式常用于角色行为管理class GameCharacter; class CharacterState { public: virtual ~CharacterState() default; virtual void handleInput(GameCharacter* character, Input input) 0; virtual void update(GameCharacter* character) 0; }; class StandingState : public CharacterState { public: void handleInput(GameCharacter* character, Input input) override { if (input PRESS_DOWN) { character-setState(std::make_uniqueDuckingState()); } else if (input PRESS_B) { character-setState(std::make_uniqueJumpingState()); } } void update(GameCharacter* character) override { // 站立状态的更新逻辑 } }; // 其他状态类DuckingState, JumpingState, AttackingState等 class GameCharacter { private: std::unique_ptrCharacterState state; int health; // 其他属性... public: GameCharacter() : state(std::make_uniqueStandingState()), health(100) {} void setState(std::unique_ptrCharacterState newState) { state std::move(newState); } void handleInput(Input input) { state-handleInput(this, input); } void update() { state-update(this); } // 其他方法... };3.3 状态模式与网络协议网络协议的状态转换是状态模式的典型应用场景class TCPConnection; class TCPState { public: virtual ~TCPState() default; virtual void transmit(TCPConnection* conn, const std::string data) 0; virtual void activeOpen(TCPConnection* conn) 0; virtual void passiveOpen(TCPConnection* conn) 0; virtual void close(TCPConnection* conn) 0; virtual void synchronize(TCPConnection* conn) 0; virtual void acknowledge(TCPConnection* conn) 0; virtual void send(TCPConnection* conn) 0; }; class TCPEstablished : public TCPState { // 实现各种操作 }; class TCPListen : public TCPState { // 实现各种操作 }; // 其他TCP状态类... class TCPConnection { private: std::unique_ptrTCPState state; public: TCPConnection() : state(std::make_uniqueTCPClosed()) {} void setState(std::unique_ptrTCPState newState) { state std::move(newState); } void transmit(const std::string data) { state-transmit(this, data); } // 其他方法... };4. 状态模式优化与最佳实践4.1 状态对象的共享如果状态对象是无状态的即不包含成员变量可以考虑共享状态实例class State { public: virtual ~State() default; virtual void handle() 0; }; class ConcreteState : public State { public: void handle() override { // 实现 } }; // 单例状态对象 ConcreteState getConcreteState() { static ConcreteState instance; return instance; } class Context { private: State* state; public: Context() : state(getConcreteState()) {} void request() { state-handle(); } };4.2 使用模板方法减少重复代码当多个状态有相似行为时可以使用模板方法模式class CommonState : public State { protected: virtual void doHandle() 0; public: void handle() final { // 公共前置处理 doHandle(); // 公共后置处理 } }; class ConcreteStateA : public CommonState { protected: void doHandle() override { // 具体处理逻辑 } };4.3 状态模式与策略模式的区别虽然状态模式和策略模式结构相似但它们的意图不同状态模式状态转换通常由状态类自身控制状态之间知道彼此的存在关注对象内部状态改变带来的行为变化策略模式策略通常由客户端指定策略之间通常不知道彼此的存在关注算法的灵活替换4.4 性能优化技巧状态预分配在系统初始化时创建所有可能的状态对象避免运行时频繁创建销毁状态缓存使用对象池管理状态对象无虚函数实现对于性能敏感场景可以使用基于标签的状态模式class Context { public: enum class State { A, B, C }; void handle() { switch(currentState) { case State::A: handleA(); break; case State::B: handleB(); break; case State::C: handleC(); break; } } void transitionTo(State newState) { currentState newState; } private: State currentState; void handleA(); void handleB(); void handleC(); };5. 状态模式实战案例5.1 订单状态管理系统class Order; class OrderState { public: virtual ~OrderState() default; virtual void pay(Order* order) 0; virtual void cancel(Order* order) 0; virtual void ship(Order* order) 0; virtual void deliver(Order* order) 0; virtual std::string toString() const 0; }; class NewOrder : public OrderState { public: void pay(Order* order) override; void cancel(Order* order) override; void ship(Order* order) override { throw std::runtime_error(不能发货未支付的订单); } void deliver(Order* order) override { throw std::runtime_error(不能交付未发货的订单); } std::string toString() const override { return 新订单; } }; // 其他订单状态类Paid, Shipped, Delivered, Cancelled class Order { private: std::unique_ptrOrderState state; std::string orderId; public: Order(const std::string id) : state(std::make_uniqueNewOrder()), orderId(id) {} void setState(std::unique_ptrOrderState newState) { state std::move(newState); } void pay() { state-pay(this); } void cancel() { state-cancel(this); } void ship() { state-ship(this); } void deliver() { state-deliver(this); } std::string getStatus() const { return state-toString(); } }; void NewOrder::pay(Order* order) { std::cout 订单已支付 std::endl; order-setState(std::make_uniquePaidOrder()); } void NewOrder::cancel(Order* order) { std::cout 订单已取消 std::endl; order-setState(std::make_uniqueCancelledOrder()); }5.2 电梯控制系统class Elevator; class ElevatorState { public: virtual ~ElevatorState() default; virtual void openDoor(Elevator* elevator) 0; virtual void closeDoor(Elevator* elevator) 0; virtual void move(Elevator* elevator, int floor) 0; virtual void stop(Elevator* elevator) 0; virtual std::string status() const 0; }; class DoorOpen : public ElevatorState { public: void openDoor(Elevator* elevator) override { std::cout 门已经是开着的 std::endl; } void closeDoor(Elevator* elevator) override; void move(Elevator* elevator, int floor) override { throw std::runtime_error(门开着时不能移动电梯); } void stop(Elevator* elevator) override { std::cout 电梯已经是停止状态 std::endl; } std::string status() const override { return 门开; } }; // 其他电梯状态类DoorClosed, Moving, Emergency class Elevator { private: std::unique_ptrElevatorState state; int currentFloor; public: Elevator() : state(std::make_uniqueDoorClosed()), currentFloor(1) {} void setState(std::unique_ptrElevatorState newState) { state std::move(newState); } void openDoor() { state-openDoor(this); } void closeDoor() { state-closeDoor(this); } void moveTo(int floor) { state-move(this, floor); } void stop() { state-stop(this); } int getCurrentFloor() const { return currentFloor; } void setCurrentFloor(int floor) { currentFloor floor; } std::string getStatus() const { return state-status(); } }; void DoorOpen::closeDoor(Elevator* elevator) { std::cout 正在关门... std::endl; elevator-setState(std::make_uniqueDoorClosed()); }5.3 媒体播放器状态控制class MediaPlayer; class PlayerState { public: virtual ~PlayerState() default; virtual void play(MediaPlayer* player) 0; virtual void pause(MediaPlayer* player) 0; virtual void stop(MediaPlayer* player) 0; virtual void next(MediaPlayer* player) 0; virtual void prev(MediaPlayer* player) 0; }; class StoppedState : public PlayerState { public: void play(MediaPlayer* player) override; void pause(MediaPlayer* player) override { std::cout 播放器已停止不能暂停 std::endl; } void stop(MediaPlayer* player) override { std::cout 播放器已经是停止状态 std::endl; } void next(MediaPlayer* player) override; void prev(MediaPlayer* player) override; }; // 其他播放器状态类PlayingState, PausedState class MediaPlayer { private: std::unique_ptrPlayerState state; std::vectorstd::string playlist; size_t currentTrack; public: MediaPlayer() : state(std::make_uniqueStoppedState()), currentTrack(0) { playlist {Track1, Track2, Track3}; } void setState(std::unique_ptrPlayerState newState) { state std::move(newState); } void play() { state-play(this); } void pause() { state-pause(this); } void stop() { state-stop(this); } void next() { state-next(this); } void prev() { state-prev(this); } const std::string getCurrentTrack() const { return playlist[currentTrack]; } void setCurrentTrack(size_t track) { if (track playlist.size()) { currentTrack track; } } }; void StoppedState::play(MediaPlayer* player) { std::cout 开始播放: player-getCurrentTrack() std::endl; player-setState(std::make_uniquePlayingState()); } void StoppedState::next(MediaPlayer* player) { player-setCurrentTrack(player-getCurrentTrack() 1); std::cout 切换到下一首: player-getCurrentTrack() std::endl; } void StoppedState::prev(MediaPlayer* player) { player-setCurrentTrack(player-getCurrentTrack() - 1); std::cout 切换到上一首: player-getCurrentTrack() std::endl; }6. 状态模式常见问题与解决方案6.1 状态对象的生命周期管理问题频繁的状态转换可能导致大量的状态对象创建和销毁解决方案使用对象池预分配状态对象共享无状态的状态对象单例模式使用std::unique_ptr确保资源安全释放class StatePool { private: std::unordered_mapstd::type_index, std::shared_ptrState pool; public: templatetypename T std::shared_ptrT getState() { auto it pool.find(typeid(T)); if (it pool.end()) { auto state std::make_sharedT(); pool[typeid(T)] state; return state; } return std::static_pointer_castT(it-second); } }; class Context { private: std::shared_ptrState currentState; StatePool pool; public: Context(StatePool p) : pool(p) { currentState pool.getStateInitialState(); } void transitionTo(const std::type_info type) { currentState pool.getStateByType(type); } };6.2 状态转换的线程安全性问题在多线程环境中状态转换可能导致竞态条件解决方案使用互斥锁保护状态转换使用原子操作将状态对象设计为不可变的class ThreadSafeContext { private: std::unique_ptrState currentState; mutable std::mutex mtx; public: void setState(std::unique_ptrState newState) { std::lock_guardstd::mutex lock(mtx); currentState std::move(newState); } void request() { std::lock_guardstd::mutex lock(mtx); currentState-handle(this); } };6.3 状态模式的测试策略单元测试建议为每个具体状态类编写独立的测试用例测试状态转换逻辑测试边界条件和异常情况TEST(StatePatternTest, StateTransitions) { Context ctx; EXPECT_TRUE(ctx.getState() typeid(StateA)); ctx.request(); EXPECT_TRUE(ctx.getState() typeid(StateB)); ctx.request(); EXPECT_TRUE(ctx.getState() typeid(StateC)); } TEST(StatePatternTest, InvalidTransition) { Context ctx; EXPECT_THROW(ctx.invalidOperation(), std::runtime_error); }6.4 状态模式与内存泄漏问题手动管理状态对象可能导致内存泄漏解决方案使用智能指针std::unique_ptr, std::shared_ptr实现清晰的资源所有权策略使用RAII原则管理资源class SafeContext { private: std::unique_ptrState currentState; public: SafeContext() : currentState(std::make_uniqueInitialState()) {} void transitionTo(std::unique_ptrState newState) { currentState std::move(newState); } // 不需要手动释放资源unique_ptr会自动处理 };6.5 状态模式的调试技巧调试建议在状态转换时添加日志输出实现状态跟踪功能使用断点观察状态变化class LoggingState : public State { protected: void logTransition(const std::string from, const std::string to) { std::cout 状态转换: from - to std::endl; } }; class ConcreteStateA : public LoggingState { public: void handle(Context* ctx) override { logTransition(StateA, StateB); ctx-transitionTo(std::make_uniqueConcreteStateB()); } };7. 状态模式与其他设计模式的结合7.1 状态模式与工厂模式使用工厂模式创建状态对象class StateFactory { public: static std::unique_ptrState createState(StateType type) { switch(type) { case StateType::A: return std::make_uniqueStateA(); case StateType::B: return std::make_uniqueStateB(); default: throw std::invalid_argument(未知状态类型); } } }; class Context { private: std::unique_ptrState currentState; public: void transitionTo(StateType type) { currentState StateFactory::createState(type); } };7.2 状态模式与观察者模式状态变化时通知观察者class ObservableState : public State { private: std::vectorObserver* observers; public: void addObserver(Observer* obs) { observers.push_back(obs); } void notifyStateChanged(Context* ctx) { for (auto obs : observers) { obs-onStateChanged(ctx); } } }; class ConcreteObservableState : public ObservableState { public: void handle(Context* ctx) override { // 状态处理逻辑 notifyStateChanged(ctx); } };7.3 状态模式与命令模式将状态转换封装为命令class StateTransitionCommand : public Command { private: Context* context; std::unique_ptrState newState; public: StateTransitionCommand(Context* ctx, std::unique_ptrState state) : context(ctx), newState(std::move(state)) {} void execute() override { context-transitionTo(std::move(newState)); } }; // 使用示例 auto cmd std::make_uniqueStateTransitionCommand( context, std::make_uniqueNextState() ); commandProcessor.addCommand(std::move(cmd));7.4 状态模式与享元模式共享状态对象以减少内存使用class StateFlyweight { private: std::unordered_mapstd::type_index, std::shared_ptrState states; public: templatetypename T std::shared_ptrT getState() { auto it states.find(typeid(T)); if (it states.end()) { auto state std::make_sharedT(); states[typeid(T)] state; return state; } return std::static_pointer_castT(it-second); } }; class Context { private: std::shared_ptrState currentState; StateFlyweight flyweight; public: Context(StateFlyweight fw) : flyweight(fw) { currentState flyweight.getStateInitialState(); } void transitionTo(const std::type_info type) { currentState flyweight.getStateByType(type); } };8. C状态模式的高级技巧8.1 使用CRTP优化状态模式奇异递归模板模式(CRTP)可以用于优化状态模式的性能templatetypename Derived class StateBase { public: void handle(Context* ctx) { static_castDerived*(this)-handleImpl(ctx); } }; class ConcreteStateA : public StateBaseConcreteStateA { public: void handleImpl(Context* ctx) { // 具体实现 ctx-template transitionToConcreteStateB(); } }; templatetypename State class Context { private: State currentState; public: templatetypename NewState void transitionTo() { currentState NewState{}; } void request() { currentState.handle(this); } };8.2 使用variant实现类型安全的状态模式C17的std::variant可以用于实现类型安全的状态模式using State std::variantStateA, StateB, StateC; class Context { private: State currentState; public: Context() : currentState(StateA{}) {} void request() { std::visit([](auto state) { using T std::decay_tdecltype(state); if constexpr (std::is_same_vT, StateA) { // 处理StateA } else if constexpr (std::is_same_vT, StateB) { // 处理StateB } }, currentState); } templatetypename NewState void transitionTo() { currentState NewState{}; } };8.3 状态模式与constexpr在编译时确定状态转换class CompileTimeState { public: constexpr virtual int nextState(int input) const 0; }; class State1 : public CompileTimeState { public: constexpr int nextState(int input) const override { return input 0 ? 2 : 1; } }; constexpr int runStateMachine(int input) { State1 s1; return s1.nextState(input); } static_assert(runStateMachine(1) 2, 状态转换测试失败);8.4 状态模式与协程C20协程可以用于实现异步状态机struct StatePromise; struct StateCoroutine : std::coroutine_handleStatePromise { using promise_type StatePromise; }; struct StatePromise { StateCoroutine get_return_object() { return {StateCoroutine::from_promise(*this)}; } std::suspend_always initial_suspend() noexcept { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } }; class AsyncStateMachine { public: StateCoroutine run() { co_await stateA(); co_await stateB(); co_await stateC(); } // 各种状态协程... };9. 状态模式的替代方案9.1 基于表驱动的状态机对于简单状态机可以使用表驱动方法struct Transition { int currentState; int event; int newState; void (*action)(); }; Transition transitions[] { {0, 1, 1, [](){ std::cout State 0 - State 1 std::endl; }}, {1, 2, 2, [](){ std::cout State 1 - State 2 std::endl; }}, // 其他转换... }; class TableDrivenFSM { private: int currentState; public: void handleEvent(int event) { for (const auto trans : transitions) { if (trans.currentState currentState trans.event event) { trans.action(); currentState trans.newState; return; } } throw std::runtime_error(无效的状态转换); } };9.2 基于枚举和switch的状态机对于状态较少的情况简单switch可能更直接enum class State { A, B, C }; class SimpleFSM { private: State currentState; public: void handleEvent(int event) { switch(currentState) { case State::A: if (event 1) { currentState State::B; // 执行动作 } break; case State::B: // 处理... break; // 其他状态... } } };9.3 基于函数指针的状态机C风格但高效的状态机实现using StateHandler void (*)(void* context); void stateA(void* ctx) { // 处理逻辑 *((StateHandler*)ctx) stateB; // 转换到状态B } void stateB(void* ctx) { // 处理逻辑 *((StateHandler*)ctx) stateC; // 转换到状态C } class FunctionPointerFSM { private: StateHandler currentState; public: FunctionPointerFSM() : currentState(stateA) {} void process() { currentState(currentState); } };10. 状态模式的性能考量10.1 虚函数调用开销状态模式通常涉及虚函数调用可能带来性能开销优化方案使用CRTP避免虚函数使用std::variant和visitor模式对于性能关键路径考虑其他实现方式10.2 内存占用分析状态模式的内存使用特点每个状态对象需要单独存储状态转换可能导致对象频繁创建销毁共享状态对象可以减少内存使用10.3 缓存友好性传统状态模式可能不利于CPU缓存改进方法将状态数据与行为分离使用基于标签的状态模式保持状态对象小而紧凑10.4 性能测试对比不同实现方式的性能对比实现方式内存使用执行速度适用场景经典状态模式中中复杂状态逻辑表驱动低高简单状态机switch-case最低最高状态数量少std::variant中高类型安全需求高在实际项目中我通常会在开发初期使用经典状态模式待设计稳定后对性能关键部分进行优化必要时转换为表驱动或其他实现方式。