状态模式(State Pattern)是行为型设计模式中的状态管理大师,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。这种模式将状态抽象为独立的类,并通过委托将行为转移给当前状态对象,实现了状态与行为的优雅解耦。本文将深入探索状态模式的核心思想、实现技巧以及在C++中的高效实践。
为什么需要状态模式?
在软件开发中,对象行为常随状态变化:
电梯的运行状态(停止、上升、下降)
TCP连接状态(建立、监听、关闭)
订单生命周期(创建、支付、发货、完成)
游戏角色状态(站立、奔跑、跳跃、攻击)
工作流引擎的状态转换
硬编码状态处理会导致:
条件爆炸:复杂的if-else或switch-case语句
维护困难:添加新状态需修改现有代码
紧耦合:状态转换逻辑与业务逻辑混杂
可读性差:状态处理逻辑分散在多个方法
状态模式通过将状态对象化解决了这些问题。
状态模式的核心概念
模式结构解析
[上下文] ↔ [状态接口]
▲
|
[具体状态A] [具体状态B]
关键角色定义
上下文(Context)
定义客户端接口
维护当前状态对象
将请求委托给状态对象处理
状态接口(State)
定义状态行为接口
封装与上下文相关的状态行为
具体状态(Concrete State)
实现状态接口
处理特定状态的行为
管理状态转换逻辑
C++实现:智能电梯控制系统
实现支持多种运行状态和故障处理的电梯系统:
#include <iostream>
#include <memory>
#include <string>
#include <map>
#include <stdexcept>
// 前置声明
class ElevatorState;
// ================= 上下文:电梯控制器 =================
class ElevatorController {
public:
ElevatorController();
// 用户操作接口
void callElevator(int floor);
void selectFloor(int floor);
void emergencyStop();
void resume();
// 系统操作
void fireAlarm();
void powerOutage();
void repairComplete();
// 状态管理
void setState(std::unique_ptr<ElevatorState> newState);
void setCurrentFloor(int floor);
int getCurrentFloor() const;
void openDoors();
void closeDoors();
void moveToFloor(int floor);
// 显示状态
void displayStatus() const;
private:
int currentFloor_ = 1;
int targetFloor_ = 1;
bool doorsOpen_ = false;
std::unique_ptr<ElevatorState> currentState_;
std::map<int, bool> floorRequests_;
};
// ================= 状态接口 =================
class ElevatorState {
public:
virtual ~ElevatorState() = default;
virtual void handleCall(ElevatorController& context, int floor) = 0;
virtual void handleSelect(ElevatorController& context, int floor) = 0;
virtual void handleEmergencyStop(ElevatorController& context) = 0;
virtual void handleResume(ElevatorController& context) = 0;
virtual void handleFireAlarm(ElevatorController& context) = 0;
virtual void handlePowerOutage(ElevatorController& context) = 0;
virtual void handleRepairComplete(ElevatorController& context) = 0;
virtual std::string getName() const = 0;
};
// ================= 具体状态:空闲状态 =================
class IdleState : public ElevatorState {
public:
void handleCall(ElevatorController& context, int floor) override;
void handleSelect(ElevatorController& context, int floor) override;
void handleEmergencyStop(ElevatorController& context) override;
void handleResume(ElevatorController&) override {}
void handleFireAlarm(ElevatorController& context) override;
void handlePowerOutage(ElevatorController& context) override;
void handleRepairComplete(ElevatorController&) override {}
std::string getName() const override { return "空闲状态"; }
};
// ================= 具体状态:运行状态 =================
class MovingState : public ElevatorState {
public:
void handleCall(ElevatorController& context, int floor) override;
void handleSelect(ElevatorController& context, int floor) override;
void handleEmergencyStop(ElevatorController& context) override;
void handleResume(ElevatorController&) override {}
void handleFireAlarm(ElevatorController& context) override;
void handlePowerOutage(ElevatorController& context) override;
void handleRepairComplete(ElevatorController&) override {}
std::string getName() const override { return "运行状态"; }
};
// ================= 具体状态:开门状态 =================
class DoorsOpenState : public ElevatorState {
public:
void handleCall(ElevatorController& context, int floor) override;
void handleSelect(ElevatorController& context, int floor) override;
void handleEmergencyStop(ElevatorController& context) override;
void handleResume(ElevatorController&) override {}
void handleFireAlarm(ElevatorController& context) override;
void handlePowerOutage(ElevatorController& context) override;
void handleRepairComplete(ElevatorController&) override {}
std::string getName() const override { return "开门状态"; }
};
// ================= 具体状态:紧急停止状态 =================
class EmergencyStopState : public ElevatorState {
public:
void handleCall(ElevatorController&, int) override {
std::cout << "紧急停止中 - 忽略呼叫请求\n";
}
void handleSelect(ElevatorController&, int) override {
std::cout << "紧急停止中 - 忽略楼层选择\n";
}
void handleEmergencyStop(ElevatorController&) override {
std::cout << "电梯已处于紧急停止状态\n";
}
void handleResume(ElevatorController& context) override;
void handleFireAlarm(ElevatorController& context) override;
void handlePowerOutage(ElevatorController& context) override;
void handleRepairComplete(ElevatorController&) override {}
std::string getName() const override { return "紧急停止状态"; }
};
// ================= 具体状态:故障状态 =================
class OutOfServiceState : public ElevatorState {
public:
void handleCall(ElevatorController&, int) override {
std::cout << "电梯故障中 - 暂停服务\n";
}
void handleSelect(ElevatorController&, int) override {
std::cout << "电梯故障中 - 暂停服务\n";
}
void handleEmergencyStop(ElevatorController&) override {
std::cout << "电梯故障中 - 已处于安全状态\n";
}
void handleResume(ElevatorController&) override {}
void handleFireAlarm(ElevatorController&) override {}
void handlePowerOutage(ElevatorController&) override {}
void handleRepairComplete(ElevatorController& context) override;
std::string getName() const override { return "故障状态"; }
};
// ================= 上下文方法实现 =================
ElevatorController::ElevatorController()
: currentState_(std::make_unique<IdleState>()) {}
void ElevatorController::setState(std::unique_ptr<ElevatorState> newState) {
std::cout << "状态变更: " << currentState_->getName()
<< " → " << newState->getName() << std::endl;
currentState_ = std::move(newState);
displayStatus();
}
void ElevatorController::callElevator(int floor) {
std::cout << "\n[操作] 呼叫电梯到 " << floor << " 楼\n";
currentState_->handleCall(*this, floor);
}
void ElevatorController::selectFloor(int floor) {
std::cout << "\n[操作] 选择前往 " << floor << " 楼\n";
currentState_->handleSelect(*this, floor);
}
void ElevatorController::emergencyStop() {
std::cout << "\n[操作] 紧急停止\n";
currentState_->handleEmergencyStop(*this);
}
void ElevatorController::resume() {
std::cout << "\n[操作] 恢复正常运行\n";
currentState_->handleResume(*this);
}
void ElevatorController::fireAlarm() {
std::cout << "\n[系统] 火警警报!\n";
currentState_->handleFireAlarm(*this);
}
void ElevatorController::powerOutage() {
std::cout << "\n[系统] 电源故障!\n";
currentState_->handlePowerOutage(*this);
}
void ElevatorController::repairComplete() {
std::cout << "\n[系统] 维修完成\n";
currentState_->handleRepairComplete(*this);
}
void ElevatorController::setCurrentFloor(int floor) {
currentFloor_ = floor;
std::cout << "电梯到达 " << floor << " 楼\n";
displayStatus();
}
int ElevatorController::getCurrentFloor() const {
return currentFloor_;
}
void ElevatorController::openDoors() {
doorsOpen_ = true;
std::cout << "电梯门已打开\n";
}
void ElevatorController::closeDoors() {
doorsOpen_ = false;
std::cout << "电梯门已关闭\n";
}
void ElevatorController::moveToFloor(int floor) {
if (floor == currentFloor_) return;
int direction = (floor > currentFloor_) ? 1 : -1;
std::cout << "电梯从 " << currentFloor_ << " 楼向 "
<< (direction > 0 ? "上" : "下") << "移动...\n";
// 模拟移动过程
while (currentFloor_ != floor) {
currentFloor_ += direction;
std::cout << "经过 " << currentFloor_ << " 楼...\n";
}
setCurrentFloor(floor);
}
void ElevatorController::displayStatus() const {
std::cout << "=== 电梯状态 ==="
<< "\n当前楼层: " << currentFloor_
<< "\n目标楼层: " << targetFloor_
<< "\n门状态: " << (doorsOpen_ ? "开" : "关")
<< "\n运行状态: " << currentState_->getName()
<< "\n================\n";
}
// ================= 状态方法实现 =================
void IdleState::handleCall(ElevatorController& context, int floor) {
context.moveToFloor(floor);
context.openDoors();
context.setState(std::make_unique<DoorsOpenState>());
}
void IdleState::handleSelect(ElevatorController& context, int floor) {
std::cout << "请先呼叫电梯到当前楼层\n";
}
void IdleState::handleEmergencyStop(ElevatorController& context) {
context.closeDoors();
context.setState(std::make_unique<EmergencyStopState>());
}
void IdleState::handleFireAlarm(ElevatorController& context) {
context.closeDoors();
context.moveToFloor(1);
context.openDoors();
std::cout << "火警警报! 电梯已移至1楼并开门\n";
}
void IdleState::handlePowerOutage(ElevatorController& context) {
context.closeDoors();
context.moveToFloor(context.getCurrentFloor()); // 确保停在当前楼层
context.setState(std::make_unique<OutOfServiceState>());
}
void MovingState::handleCall(ElevatorController& context, int floor) {
std::cout << "已记录 " << floor << " 楼的呼叫请求\n";
// 记录请求,稍后处理
}
void MovingState::handleSelect(ElevatorController& context, int floor) {
std::cout << "已记录前往 " << floor << " 楼的请求\n";
// 记录请求,稍后处理
}
void MovingState::handleEmergencyStop(ElevatorController& context) {
context.moveToFloor(context.getCurrentFloor()); // 立即停止在当前楼层
context.closeDoors();
context.setState(std::make_unique<EmergencyStopState>());
}
void MovingState::handleFireAlarm(ElevatorController& context) {
context.closeDoors();
context.moveToFloor(1);
context.openDoors();
context.setState(std::make_unique<DoorsOpenState>());
std::cout << "火警警报! 电梯已移至1楼并开门\n";
}
void MovingState::handlePowerOutage(ElevatorController& context) {
context.moveToFloor(context.getCurrentFloor()); // 确保停在当前楼层
context.closeDoors();
context.setState(std::make_unique<OutOfServiceState>());
}
void DoorsOpenState::handleCall(ElevatorController& context, int floor) {
std::cout << "请先关闭电梯门\n";
}
void DoorsOpenState::handleSelect(ElevatorController& context, int floor) {
context.closeDoors();
context.moveToFloor(floor);
context.openDoors();
}
void DoorsOpenState::handleEmergencyStop(ElevatorController& context) {
context.closeDoors();
context.setState(std::make_unique<EmergencyStopState>());
}
void DoorsOpenState::handleFireAlarm(ElevatorController& context) {
context.closeDoors();
context.moveToFloor(1);
context.openDoors();
std::cout << "火警警报! 电梯已移至1楼并开门\n";
}
void DoorsOpenState::handlePowerOutage(ElevatorController& context) {
context.closeDoors();
context.setState(std::make_unique<OutOfServiceState>());
}
void EmergencyStopState::handleResume(ElevatorController& context) {
context.setState(std::make_unique<IdleState>());
}
void EmergencyStopState::handleFireAlarm(ElevatorController& context) {
context.closeDoors();
context.moveToFloor(1);
context.openDoors();
std::cout << "火警警报! 电梯已移至1楼并开门\n";
}
void EmergencyStopState::handlePowerOutage(ElevatorController& context) {
context.setState(std::make_unique<OutOfServiceState>());
}
void OutOfServiceState::handleRepairComplete(ElevatorController& context) {
context.setState(std::make_unique<IdleState>());
}
// ================= 客户端代码 =================
int main() {
ElevatorController elevator;
elevator.displayStatus();
// 正常使用流程
elevator.callElevator(3);
elevator.selectFloor(5);
elevator.selectFloor(1);
// 测试紧急停止
elevator.emergencyStop();
elevator.resume();
// 测试故障状态
elevator.powerOutage();
elevator.repairComplete();
// 测试火警
elevator.callElevator(7);
elevator.fireAlarm();
return 0;
}
状态模式的五大优势
消除条件分支
// 无需switch-case void handleRequest() { currentState_->handleRequest(); // 委托给状态对象 }
状态对象化
class IdleState : public State { void handleAction() override { // 空闲状态特定行为 } };
单一职责原则
// 每个状态类只关注特定状态的行为 class MovingState : public State { /* 移动相关行为 */ };
开放封闭原则
// 添加新状态不影响现有代码 class MaintenanceState : public State { /* 新增维护状态 */ };
状态转换显式化
void changeState(State* newState) { // 明确的状态转换点 }
状态模式的高级应用
1. 状态表驱动
class StateTable {
public:
struct Transition {
State* nextState;
void (State::*action)(Context&);
};
void addTransition(State* from, Event event, Transition trans) {
transitions_[from][event] = trans;
}
void handleEvent(Context& context, Event event) {
auto& stateTrans = transitions_[context.currentState()];
if (stateTrans.find(event) != stateTrans.end()) {
auto& trans = stateTrans[event];
(trans.action)(context); // 执行状态动作
context.changeState(trans.nextState); // 转换状态
}
}
private:
std::map<State*, std::map<Event, Transition>> transitions_;
};
2. 分层状态机
class HierarchicalState : public State {
public:
void handleEvent(Context& context, Event event) override {
if (currentSubState_ && currentSubState_->handleEvent(context, event)) {
return;
}
// 当前状态处理
State::handleEvent(context, event);
}
void setSubState(State* substate) {
currentSubState_ = substate;
}
private:
State* currentSubState_ = nullptr;
};
class RunningState : public HierarchicalState {
// 包含子状态:加速、匀速、减速
};
3. 状态历史管理
class StateHistory {
public:
void push(State* state) {
history_.push(state);
}
State* pop() {
if (history_.empty()) return nullptr;
auto state = history_.top();
history_.pop();
return state;
}
void clear() {
while (!history_.empty()) history_.pop();
}
private:
std::stack<State*> history_;
};
class Context {
void returnToPreviousState() {
if (auto prevState = history_.pop()) {
setState(prevState);
}
}
};
状态模式的应用场景
1. 网络协议实现
class TCPConnection {
public:
void open() {
state_->open(this);
}
void transmit(const std::string& data) {
state_->transmit(this, data);
}
void close() {
state_->close(this);
}
private:
TCPState* state_;
};
class TCPEstablished : public TCPState {
void transmit(TCPConnection* conn, const std::string& data) override {
// 传输数据
}
void close(TCPConnection* conn) override {
// 切换到关闭状态
conn->changeState(new TCPClosed());
}
};
2. 游戏角色状态
class GameCharacter {
public:
void update() {
state_->update(this);
}
void handleInput(Input input) {
state_->handleInput(this, input);
}
private:
CharacterState* state_;
};
class JumpingState : public CharacterState {
void update(GameCharacter* character) override {
// 跳跃物理逻辑
if (character->isOnGround()) {
character->changeState(new StandingState());
}
}
void handleInput(GameCharacter* character, Input input) override {
if (input == Input::ATTACK) {
character->changeState(new JumpAttackState());
}
}
};
3. 订单处理系统
class Order {
public:
void process() {
state_->process(this);
}
void cancel() {
state_->cancel(this);
}
void ship() {
state_->ship(this);
}
private:
OrderState* state_;
};
class ShippedState : public OrderState {
void process(Order* order) override {
// 已发货订单处理逻辑
}
void cancel(Order* order) override {
// 已发货订单不能取消
throw std::runtime_error("已发货订单不能取消");
}
};
状态模式与其他模式的关系
模式 | 关系 | 区别 |
---|---|---|
策略 | 结构相似,意图不同 | 策略模式选择算法,状态模式管理状态转换 |
命令 | 都可封装行为 | 命令封装操作,状态封装状态相关行为 |
享元 | 共享状态对象 | 享元共享对象,状态模式管理状态转换 |
单例 | 状态对象可共享 | 单例确保唯一实例,状态模式管理状态 |
组合使用示例:
// 状态模式 + 享元模式
class StateFactory {
public:
State* getState(StateType type) {
if (states_.find(type) == states_.end()) {
states_[type] = createState(type);
}
return states_[type];
}
private:
std::map<StateType, State*> states_;
};
// 上下文使用
context->setState(factory.getState(StateType::IDLE));
状态模式的挑战与解决方案
挑战 | 解决方案 |
---|---|
状态类膨胀 | 使用表驱动状态机 |
状态转换复杂 | 引入状态管理中间层 |
共享状态数据 | 使用上下文存储共享数据 |
性能开销 | 状态对象复用(享元模式) |
表驱动状态机示例:
class StateMachine {
public:
void handleEvent(Event event) {
auto& actions = transitions_[currentState_];
if (actions.find(event) != actions.end()) {
actions[event](this); // 执行动作
}
}
void addTransition(State state, Event event, Action action, State nextState) {
transitions_[state][event] = [=](StateMachine* sm) {
action(sm); // 执行动作
sm->currentState_ = nextState; // 状态转换
};
}
private:
State currentState_;
std::map<State, std::map<Event, std::function<void(StateMachine*)>>> transitions_;
};
总结
状态模式是管理复杂状态转换的终极工具,它通过:
状态封装:每个状态成为独立类
行为委托:上下文将行为委托给当前状态
显式转换:清晰的状态转换逻辑
解耦设计:分离状态与行为
适用场景:
对象行为随状态改变
存在大量条件状态判断
状态转换逻辑复杂
需要清晰的状态生命周期管理
"状态模式不是简单的状态切换,而是将状态提升为一等公民。它是复杂行为管理的优雅范式。" — 设计模式实践者