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

news/2025/2/24 16:57:37

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

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

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

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

模式结构图


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

2.1 基础框架搭建

#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 具体状态实现(以开门状态为例)


// 具体状态
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 状态切换演示

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 状态共享优化

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

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

4.2 状态转换表管理

// 使用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个
  • 状态转换逻辑复杂
  • 需要频繁添加新状态
  • 存在大量重复的状态判断代码

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


http://www.niftyadmin.cn/n/5864623.html

相关文章

python基于深度学习实现遮挡人脸识别系统的详细方案

以下是一个基于深度学习实现遮挡人脸识别系统的详细方案,使用Python语言: 一、需求理解 遮挡人脸识别系统旨在准确识别出即使面部部分被遮挡(如口罩、眼镜等)的人的身份。该系统将利用深度学习技术,结合合适的数据集进行训练,以达到较高的识别准确率。 二、系统架构 …

简识Kafka集群与RocketMQ集群的核心区别

前记&#xff1a;各位潘安、各位子健/各位彦祖、于晏&#xff0c;文字较多&#xff0c;优先看目录。 Kafka集群与RocketMQ集群的核心区别及架构图例说明 一、核心区别对比 特性Kafka 集群RocketMQ 集群设计目标高吞吐量实时日志流系统&#xff08;如日志收集、大数据流水线&a…

神经网络八股(2)

1.数据增强算法 基于样本变换的数据增强&#xff1a;旋转&#xff0c;翻转&#xff0c;缩放&#xff0c;裁剪&#xff0c;噪声添加&#xff0c;色彩调整&#xff08;亮度&#xff0c;对比度&#xff09; 混合数据增强方法&#xff1a;mixup&#xff08;两张图像按照一定混合成…

Uniapp 中布局魔法:display 属性

一、开启 Uniapp 布局魔法之旅 各位 Uniapp 开发的小伙伴们&#xff0c;欢迎来到 Uniapp 这个充满创意和挑战的魔法世界&#xff01;在构建跨平台应用时&#xff0c;页面布局就像是搭建一座梦幻城堡&#xff0c;而 display 属性则是我们手中的神奇魔杖&#xff0c;能让元素们按…

【Redis原理】底层数据结构 五种数据类型

文章目录 动态字符串SDS(simple dynamic string )SDS结构定义SDS动态扩容 IntSetIntSet 结构定义IntSet的升级 DictDict结构定义Dict的扩容Dict的收缩Dict 的rehash ZipListZipListEntryencoding 编码字符串整数 ZipList的连锁更新问题 QuickListQuickList源码 SkipListRedisOb…

web网络安全:跨站脚本攻击(XSS)

跨站脚本攻击&#xff08;XSS&#xff09;概述 跨站脚本攻击&#xff08;XSS&#xff0c;Cross-Site Scripting&#xff09; 是一种常见的 Web 安全漏洞&#xff0c;攻击者通过向受信任的网站注入恶意脚本&#xff08;通常是 JavaScript&#xff09;&#xff0c;诱使其他用户在…

Leetcode 3463. Check If Digits Are Equal in String After Operations II

Leetcode 3463. Check If Digits Are Equal in String After Operations II 1. 解题思路2. 代码实现 题目链接&#xff1a;3463. Check If Digits Are Equal in String After Operations II 1. 解题思路 这道题是题目Leetcode 3461的进阶版本&#xff0c;其实就是提高了对于…

蓝桥杯定时器实现led闪烁

step1.配置定时器&#xff0c;TIM1时高级定时&#xff0c;TIM2是通用定时器&#xff0c;用TIM2就行&#xff0c;用内部时钟源&#xff0c;记住相关公式&#xff0c;定时器中断配置时要使能&#xff0c;且生成代码后也要在mian中写使能函数 step2.写代码 配置生成代码后多出的…