设计模式 | 状态模式

发布于:2025-07-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

状态模式(State Pattern)是行为型设计模式中的状态管理大师,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。这种模式将状态抽象为独立的类,并通过委托将行为转移给当前状态对象,实现了状态与行为的优雅解耦。本文将深入探索状态模式的核心思想、实现技巧以及在C++中的高效实践。


为什么需要状态模式?

在软件开发中,对象行为常随状态变化:

  • 电梯的运行状态(停止、上升、下降)

  • TCP连接状态(建立、监听、关闭)

  • 订单生命周期(创建、支付、发货、完成)

  • 游戏角色状态(站立、奔跑、跳跃、攻击)

  • 工作流引擎的状态转换

硬编码状态处理会导致:
条件爆炸:复杂的if-else或switch-case语句
维护困难:添加新状态需修改现有代码
紧耦合:状态转换逻辑与业务逻辑混杂
可读性差:状态处理逻辑分散在多个方法

状态模式通过将状态对象化解决了这些问题。


状态模式的核心概念

模式结构解析
[上下文] ↔ [状态接口] 
              ▲
              |
        [具体状态A] [具体状态B]
关键角色定义
  1. 上下文(Context)

    • 定义客户端接口

    • 维护当前状态对象

    • 将请求委托给状态对象处理

  2. 状态接口(State)

    • 定义状态行为接口

    • 封装与上下文相关的状态行为

  3. 具体状态(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;
}

状态模式的五大优势

  1. 消除条件分支

    // 无需switch-case
    void handleRequest() {
        currentState_->handleRequest(); // 委托给状态对象
    }
  2. 状态对象化

    class IdleState : public State {
        void handleAction() override {
            // 空闲状态特定行为
        }
    };
  3. 单一职责原则

    // 每个状态类只关注特定状态的行为
    class MovingState : public State { /* 移动相关行为 */ };
  4. 开放封闭原则

    // 添加新状态不影响现有代码
    class MaintenanceState : public State { /* 新增维护状态 */ };
  5. 状态转换显式化

    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_;
};

总结

状态模式是管理复杂状态转换的终极工具,它通过:

  • 状态封装:每个状态成为独立类

  • 行为委托:上下文将行为委托给当前状态

  • 显式转换:清晰的状态转换逻辑

  • 解耦设计:分离状态与行为

适用场景

  • 对象行为随状态改变

  • 存在大量条件状态判断

  • 状态转换逻辑复杂

  • 需要清晰的状态生命周期管理

"状态模式不是简单的状态切换,而是将状态提升为一等公民。它是复杂行为管理的优雅范式。" — 设计模式实践者


网站公告

今日签到

点亮在社区的每一天
去签到