「软件设计模式」状态模式(State)

软件设计模式深度解析:状态模式及其C++实践

一、模式思想:行为的状态化封装

状态模式(State Pattern)是面向对象设计中的行为型模式,其核心思想是将对象的行为封装到独立的状态对象 中,使得对象能根据内部状态的变化动态改变行为。该模式通过以下方式解耦程序逻辑:

  1. 将每个状态的行为抽象为独立类
  2. 允许对象在运行时切换状态对象
  3. 消除复杂的条件判断语句

模式结构图

复制代码

二、模式实现:电梯状态控制实例

2.1 基础框架搭建

cpp 复制代码
#include <iostream>
using namespace std;

// 前置声明
class ClosedState;
class MovingState;
class StoppedState;

// 状态接口
class ElevatorState {
public:
    virtual void openDoors() = 0;
    virtual void closeDoors() = 0;
    virtual void move() = 0;
    virtual void stop() = 0;
    virtual ~ElevatorState() = default;
};

// 上下文环境
class Elevator {
    ElevatorState* currentState;

public:
    Elevator() : currentState(nullptr) {}

    void setState(ElevatorState* newState) {
        delete currentState; // 释放旧状态
        currentState = newState;
    }

    void openDoors() {
        currentState->openDoors();
    }
    void closeDoors() {
        currentState->closeDoors();
    }
    void move() {
        currentState->move();
    }
    void stop() {
        currentState->stop();
    }
};

2.2 具体状态实现(以开门状态为例)

cpp 复制代码
// 具体状态
class OpenState : public ElevatorState {
    Elevator* elevator;

public:
    OpenState(Elevator* e) : elevator(e) {}

    void openDoors() override {
        cout << "电梯门已经是开启状态" << endl;
    }

    void closeDoors() override {
        cout << "正在关闭电梯门..." << endl;
        elevator->setState(new ClosedState(elevator));
    }

    void move() override {
        cout << "错误:门未关闭不能移动" << endl;
    }

    void stop() override {
        cout << "电梯已处于静止状态" << endl;
    }
};

class ClosedState : public ElevatorState {
    Elevator* elevator;

public:
    ClosedState(Elevator* e) : elevator(e) {}

    void openDoors() override {
        elevator->setState(new OpenState(elevator));
        cout << "电梯门已开启" << endl;
    }

    void closeDoors() override {
        cout << "电梯门已经是关闭状态" << endl;
    }

    void move() override {
        cout << "电梯开始移动..." << endl;
        elevator->setState(new MovingState(elevator));
    }

    void stop() override {
        cout << "电梯已处于静止状态" << endl;
    }
};

class MovingState : public ElevatorState {
    Elevator* elevator;

public:
    MovingState(Elevator* e) : elevator(e) {}

    void openDoors() override {
        cout << "错误:电梯移动中不能开门" << endl;
    }

    void closeDoors() override {
        cout << "电梯门已经是关闭状态" << endl;
    }

    void move() override {
        cout << "电梯已经在移动中" << endl;
    }

    void stop() override {
        cout << "电梯停止..." << endl;
        elevator->setState(new StoppedState(elevator));
    }
};

class StoppedState : public ElevatorState {
    Elevator* elevator;

public:
    StoppedState(Elevator* e) : elevator(e) {}

    void openDoors() override {
        cout << "电梯门已开启" << endl;
        elevator->setState(new OpenState(elevator));
    }

    void closeDoors() override {
        cout << "电梯门已经是关闭状态" << endl;
    }

    void move() override {
        cout << "电梯开始移动..." << endl;
        elevator->setState(new MovingState(elevator));
    }

    void stop() override {
        cout << "电梯已经处于静止状态" << endl;
    }
};

2.3 状态切换演示

cpp 复制代码
int main() {
    // 创建电梯对象
    Elevator elevator;

    // 设置初始状态为停止状态
    elevator.setState(new StoppedState(&elevator));

    // 测试电梯状态转换
    elevator.openDoors();  // 电梯门已开启
    elevator.closeDoors(); // 正在关闭电梯门...
    elevator.move();       // 电梯开始移动...
    elevator.stop();       // 电梯停止...
    elevator.openDoors();  // 错误:电梯移动中不能开门

    return 0;
}

三、模式优势与适用场景

3.1 核心优势

  1. 单一职责原则:每个状态对应一个类
  2. 开闭原则:新增状态无需修改现有代码
  3. 消除巨型条件语句:将分支逻辑转化为对象
  4. 状态转换显式化:状态机清晰可见

3.2 典型应用场景

  • 对象行为随状态改变而变化的场景
  • 需要替代复杂条件状态判断语句
  • 存在大量状态相关代码且频繁变更
  • 需要清晰的状态转换控制流程

四、进阶实践技巧

4.1 状态共享优化

cpp 复制代码
// 使用静态成员实现状态共享
class RunningState : public ElevatorState {
    static RunningState* instance;
    // ... 实现单例模式
};

// 上下文调用方式
elevator.setState(RunningState::getInstance());

4.2 状态转换表管理

cpp 复制代码
// 使用map管理状态转换规则
unordered_map<Type, function<State*()>> transitionTable = {
    {OPEN_EVENT, [](){ return new OpenState(); }},
    {CLOSE_EVENT, [](){ return new ClosedState(); }}
};

五、模式对比与常见问题

5.1 状态模式 vs 策略模式

特性 状态模式 策略模式
切换机制 状态自动转换 客户端显式指定
对象关系 状态间相互知晓 策略相互独立
主要目的 管理状态依赖行为 灵活替换算法

5.2 常见问题解答

Q:如何处理状态间的循环依赖?

A:采用中介者模式解耦状态交互

Q:状态对象是否需要持有上下文引用?

A:推荐使用弱引用或通过参数传递

Q:如何实现状态历史追溯?

A:使用备忘录模式保存状态栈

六、总结与延伸思考

状态模式将容易失控的状态判断逻辑转化为可维护的对象结构,特别适合实现复杂的状态机。当系统存在以下特征时建议采用该模式:

  • 状态数量超过5个
  • 状态转换逻辑复杂
  • 需要频繁添加新状态
  • 存在大量重复的状态判断代码

性能优化方向:对于高频率状态切换场景,可结合对象池技术复用状态对象,避免频繁的内存分配。

相关推荐
晨米酱5 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机10 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机11 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤11 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式