【C++设计模式之状态模式:行为型】分析及示例

简介

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,看起来就像是改变了其类。状态模式将对象的状态封装成不同的类,并使得对象在不同状态下有不同的行为。

描述

状态模式通过将每种状态封装成一个独立的类,然后将具体状态类的行为委托给Context类,使得Context类在不同的状态下具有不同的行为。这样,当Context对象的状态发生变化时,它的行为也会随之改变。

原理

状态模式由三个核心组件组成:Context(上下文类)、State(抽象状态类)和ConcreteState(具体状态类)。

  • Context类负责定义切换状态的口,并维护一个对当前状态对象的引用。Context类将具体的状态行为委托给当前状态对象。
  • State类是一个抽象类,定义了具体状态类需要实现的方法,以及在不同状态下Context对象应该具有的行为。
  • ConcreteState类是具体的状态类,实现了State类定义的方法,并根据当前状态下的需求来执行相应的逻辑。

类图

在这里插入图片描述

示例

假设有一个电梯系统,其中电梯有三种状态:打开状态(OpenState)、关闭状态(ClosedState)运行状态(RunningState)。当电梯处于不同的状态时,它的行为也不同。

C++示例代码如下:

#include <iostream>// Context
class Elevator {
public:virtual void open() = 0;virtual void close() = 0;virtual void run() = 0;
};// State
class ElevatorState {
public:virtual void open(Elevator* elevator) = 0;virtual void close(Elevator* elevator) = 0;virtual void run(Elevator* elevator) = 0;
};// ConcreteState
class OpenState : public ElevatorState {
public:void open(Elevator* elevator) override {std::cout << "The elevator is already open." << std::endl;}void close(Elevator* elevator) override {std::cout << "Closing the elevator..." << std::endl;elevator->setState(new ClosedState());}void run(Elevator* elevator) override {std::cout << "Cannot run the elevator while it is open." << std::endl;}
};class ClosedState : public ElevatorState {
public:void open(Elevator* elevator) override {std::cout << "Opening the elevator..." << std::endl;elevator->setState(new OpenState());}void close(Elevator* elevator) override {std::cout << "The elevator is already closed." << std::endl;}void run(Elevator* elevator) override {std::cout << "Running the elevator..." << std::endl;elevator->setState(new RunningState());}
};class RunningState : public ElevatorState {
public:void open(Elevator* elevator) override {std::cout << "Cannot open the elevator while it is running." << std::endl;}void close(Elevator* elevator) override {std::cout << "Cannot close the elevator while it is running." << std::endl;}void run(Elevator* elevator) override {std::cout << "The elevator is already running." << std::endl;}
};// Concrete Context
class ElevatorSystem : public Elevator {
public:ElevatorSystem() {currentState = new ClosedState();}void setState(ElevatorState* state) {delete currentState;currentState = state;}void open() override {currentState->open(this);}void close() override {currentState->close(this);}void run() override {currentState->run(this);}private:ElevatorState* currentState;
};// 使用示例
int main() {ElevatorSystem system;system.open();  // Opening the elevator...system.open();  // The elevator is already open.system.close(); // Closing the elevator...system.run();   // Running the elevator...system.close(); // The elevator is already closed.system.open();  // Opening the elevator...system.run();   // Cannot run the elevator while it is open.return 0;
}

输出结果

Opening the elevator...
The elevator is already open.
Closing the elevator...
Running the elevator...
The elevator is already closed.
Opening the elevator...
Cannot run the elevator while it is open.

解释

在上述示例中,Elevator类是上下文类(Context),它定义了切换状态的接口,并维护一个对当前状态对象的引用。ElevatorState是抽象状态类(State),它定义了具体状态类需要实现的方法。OpenState、ClosedState和RunningState是具体状态类(ConcreteState),它们分别实现了ElevatorState的方法,并根据当前状态下的需求执行相应的逻辑。
在示例中,创建了一个电梯系统(ElevatorSystem),初始状态为关闭状态(ClosedState)。通过调用ElevatorSystem的open、close和run方法来切换电梯的状态,并根据不同的状态执行相应的操作。

结论

状态模式通过将对象的状态封装成独立的类,并委托给Context类来管理,达到了解耦的目的。当对象的状态发生变化时,它的行为也会相应地发生变化。

状态模式适用于以下情况:

  • 当一个对象的行为取决于其状态,并且需要在运行时根据状态改变行为时,可以使用状态模式。
  • 当一个类有很多状态,并且状态之间的转换非常复杂时,可以使用状态模式来将每个状态的行为解耦合。

状态模式常见的应用场景包括订单状态管理、电梯状态控制、游戏角色状态机等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/127960.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis的五种常用数据类型

1.字符串 String的数据结构是简单的Key-Value模型&#xff0c;Value可以是字符串&#xff0c;也可以是数字。 String是Redis最基本的类型&#xff0c;是二进制安全的&#xff0c;意味着Redis的string可以包含任何数据&#xff0c;比如jpg图片。 一个redis中字符串value最大是…

整理mongodb文档:副本集二

个人博客 整理mongodb文档:副本集二 个人博客&#xff0c;求推荐&#xff0c;本片内容较为乱 文章概叙 本文章主要讲在MongoDB的副本集中的一些注意点&#xff0c;主要是如何对seconadry进行数据操作&#xff0c;以及对更新数据的一些介绍 查看当前节点 上一集讲了关于搭…

B (1089) : DS单链表--合并

Description 假定两个单链表是递增有序&#xff0c;定义并实现以下函数&#xff0c;完成两个单链表的合并&#xff0c;继续保持递增有序 int LL_merge(ListNode *La, ListNode *Lb) Input 第1行先输入n表示有n个数据&#xff0c;接着输入n个数据 第2行先输入m表示有M个数据…

TSINGSEE青犀基于AI视频智能分析的客流统计分析场景方案

随着AI技术的不断发展与人类需求的不断提升&#xff0c;视觉目标的检测识别、智能监控在人们的生活中均有着广泛的应用。其中&#xff0c;智能安防视频监控是计算机视觉的重要应用领域&#xff0c;而AI客流统计则是近年来此领域大家关注热度较高的技术之一。 行业痛点 传统的客…

【抢先体验】开通使用 ChatGPT 语音版功能保姆级教程

大家好&#xff0c;我是苍何&#xff0c;一个土木转码的非典型程序员&#xff0c;也是一名技术管理者&#xff0c;同时也是 AI 应用的探索者。今天在视频号上看到和 ChatGPT 语音对话的视频&#xff0c;其声音的真实感太让人震撼了&#xff0c;于是也想去抢先体验一下 ChatGPT …

互联网项目有哪些值得做的

互联网已经融入了我们生活的方方面面&#xff0c;从电商巨头到科技创新&#xff0c;互联网带来的变革和便利无处不在。而在这个信息广泛的时代&#xff0c;越来越多的人开始思考如何利用互联网去创造价值。现如今&#xff0c;互联网项目的形式多种多样&#xff0c;有些让我们的…

python—如何提取word中指定内容

假设有一个Word&#xff0c;该Word中存在 “联系人” 关键字&#xff0c;如何将该Word中的联系人所对应的内容提取出来呢&#xff1f; 该Word内容如下所示&#xff1a; 要在给定的Word文档中提取出与"联系人"关键字对应的内容&#xff0c;可以使用Python的py…

详解链表oJ<反转链表,链表的中间节点及链表的回文>

hello&#xff0c;大家好&#xff0c;这里是Dark FlameMaster,今天和大家分享的是有关数据结构链表的几道题目&#xff0c;链表的中间节点&#xff0c;反转链表及判断链表是否为回文结构&#xff0c;放在一起讲解会印象更加深刻。 文章目录 一&#xff0c;链表的中间节点二&…

你的librosa和scikit-learn打架了吗?

被这个问题困扰好久&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 我的原来版本librosa0.7.1 和 scikit-learn1.3.1 一直拆了按&#xff0c;按…

【力扣每日一题】2023.10.7 股票价格跨度

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们一个数组表示不同时间的股票的价格&#xff0c;要我们按照顺序返回每天的股票价格跨度&#xff0c;价格跨度就是股票价格小于或等于…

Python3操作Redis最新版|CRUD基本操作(保姆级)

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 Python3数据科学包系列(三):数据分析实战 Win11查看安装的Python路…

C#练习题-构造函数

文章目录 前言题目习题1运行示例 习题2运行示例 参考答案习题1习题2 其他文章 前言 本篇文章的题目为C#的基础练习题&#xff0c;构造函数部分。做这些习题之前&#xff0c;你需要确保已经学习了构造函数的知识。 本篇文章可以用来在学完构造函数后加深印象&#xff0c;也可以…