当前位置: 首页 > news >正文

【30】c++设计模式——>状态模式

状态模式概述

状态模式是一种行为型设计模式,它可以让一个对象在其内部状态发生变化时更改其行为。通过将每个状态封装成一个独立的类,我们可以使状态之间互相独立,并且使得状态的切换变得更加灵活、可扩展。(多个状态之间可以相互转换)
在状态模式中,我们通常会定义一个抽象状态类(Abstract State),以及多个具体状态类(Concrete States)。每个具体状态都会实现抽象状态类中定义的各种操作,并且在需要时执行状态转换。
此外,还有一个环境类(Context),它包含了当前状态,并且在状态发生变化时调用各个状态类的方法来实现状态转换。因为这些状态类都实现了同一个接口,所以环境类不需要知道具体状态的细节,只需要调用相应的方法即可。

如何理解状态类和环境类

电视遥控器
开电视学习
关电视睡觉
静音打游戏

电视遥控器的例子

一个电视遥控器。电视遥控器有三种状态:开机状态、关机状态和静音状态。我们可以通过简单地按遥控器上的按钮来更改状态。为了实现这个功能,首先我们需要定义一个抽象状态类,该类将定义所有可能的操作:

class TVState {
public:virtual void onButtonPressed(TVRemote* remote) = 0;virtual void offButtonPressed(TVRemote* remote) = 0;virtual void muteButtonPressed(TVRemote* remote) = 0;
};

TVState中包含了三种操作:开机、关机和静音。这些操作在不同的状态下可能会有不同的实现方式,因此我们需要在具体状态类中进行实现。

// 具体状态类:开机状态
class OnState : public TVState {
public:void onButtonPressed(TVRemote* remote) override {std::cout << "The TV is already on." << std::endl;}void offButtonPressed(TVRemote* remote) override {std::cout << "Turning off the TV." << std::endl;remote->setState(new OffState());}void muteButtonPressed(TVRemote* remote) override {std::cout << "Muting the TV." << std::endl;remote->setState(new MuteState());}
};// 具体状态类:关机状态
class OffState : public TVState {
public:void onButtonPressed(TVRemote* remote) override {std::cout << "Turning on the TV." << std::endl;remote->setState(new OnState());}void offButtonPressed(TVRemote* remote) override {std::cout << "The TV is already off." << std::endl;}void muteButtonPressed(TVRemote* remote) override {std::cout << "Cannot mute the TV when it's turned off." << std::endl;}
};// 具体状态类:静音状态
class MuteState : public TVState {
public:void onButtonPressed(TVRemote* remote) override {std::cout << "Unmuting the TV." << std::endl;remote->setState(new OnState());}void offButtonPressed(TVRemote* remote) override {std::cout << "Turning off the TV." << std::endl;remote->setState(new OffState());}void muteButtonPressed(TVRemote* remote) override {std::cout << "The TV is already muted." << std::endl;}
};

在这些具体状态类中,我们重写了TVState中定义的所有操作,并且在需要时执行状态转换。例如,在开机状态下按下静音键会将遥控器的状态更改为“静音状态”。
接下来,让我们定义环境类(Context):

class TVRemote {
private:TVState* currentState;public:TVRemote() {currentState = new OffState();}void setState(TVState* state) {currentState = state;}void pressOnButton() {currentState->onButtonPressed(this);}void pressOffButton() {currentState->offButtonPressed(this);}void pressMuteButton() {currentState->muteButtonPressed(this);}
};

在环境类中,我们维护了当前状态,并且在状态发生变化时调用相应的具体状态类方法。我们还定义了三个按键操作:开机、关机和静音。
现在,我们可以使用电视遥控器来测试状态模式的实现了:

int main() {TVRemote remote;remote.pressOnButton();    // Turning on the TV.remote.pressOnButton();    // The TV is already on.remote.pressMuteButton();  // Muting the TV.remote.pressMuteButton();  // The TV is already muted.remote.pressOffButton();   // Turning off the TV.remote.pressOffButton();   // The TV is already off.remote.pressMuteButton();  // Cannot mute the TV when it's turned off.remote.pressOnButton();    // Turning on the TV.remote.pressMuteButton();  // Unmuting the TV.return 0;
}

通过上面的代码,我们可以看到当我们按下不同的键时,电视遥控器的状态会发生相应的变化。

完整代码

remote.cpp

#include "remote.h"
#include "state.h"TVRemote::TVRemote(TVState* State )
{currentState = State;
}void TVRemote::setState(TVState* state)
{currentState = state;
}void TVRemote::pressOnButton()
{currentState->onButtonPressed(this);
}void TVRemote::pressOffButton()
{currentState->offButtonPressed(this);
}void TVRemote::pressMuteButton()
{currentState->muteButtonPressed(this);
}

remote.h

#pragma once
class TVState; //这里没声明,报了一堆错class TVRemote
{
private:TVState* currentState;public:TVRemote(TVState* State);void setState(TVState* state);void pressOnButton();void pressOffButton();void pressMuteButton();
};

state.h

#pragma once
#include"remote.h"class TVState {
public:virtual void onButtonPressed(TVRemote* remote) = 0; // 开机virtual void offButtonPressed(TVRemote* remote) = 0; // 关机virtual void muteButtonPressed(TVRemote* remote) = 0; // 静音
};// 具体状态类:关机状态
class OffState : public TVState
{
public:void onButtonPressed(TVRemote* remote) override;void offButtonPressed(TVRemote* remote) override;void muteButtonPressed(TVRemote* remote) override;
};// 具体状态类:开机状态
class OnState : public TVState
{
public:void onButtonPressed(TVRemote* remote) override;void offButtonPressed(TVRemote* remote) override;void muteButtonPressed(TVRemote* remote) override;
};// 具体状态类:静音状态
class MuteState : public TVState {
public:void onButtonPressed(TVRemote* remote) override;void offButtonPressed(TVRemote* remote) override;void muteButtonPressed(TVRemote* remote) override;
};

state.cpp

#include<iostream>
#include "state.h"
#include "remote.h"// 具体状态类:关机状态
void OffState::onButtonPressed(TVRemote* remote) 
{std::cout << "Turning on the TV." << std::endl;remote->setState(new OnState());
}void OffState::offButtonPressed(TVRemote* remote) 
{std::cout << "The TV is already off." << std::endl;
}void OffState::muteButtonPressed(TVRemote* remote)
{std::cout << "Cannot mute the TV when it's turned off." << std::endl;
}// 具体状态类:开机状态
void OnState::onButtonPressed(TVRemote* remote) 
{std::cout << "The TV is already on." << std::endl;
}void OnState::offButtonPressed(TVRemote* remote) 
{std::cout << "Turning off the TV." << std::endl;remote->setState(new OffState());
}void OnState::muteButtonPressed(TVRemote* remote)
{std::cout << "Muting the TV." << std::endl;remote->setState(new MuteState());
}// 具体状态类:静音状态
void MuteState::onButtonPressed(TVRemote* remote)
{std::cout << "Unmuting the TV." << std::endl;remote->setState(new OnState());
}void MuteState::offButtonPressed(TVRemote* remote) 
{std::cout << "Turning off the TV." << std::endl;remote->setState(new OffState());
}void MuteState::muteButtonPressed(TVRemote* remote)
{std::cout << "The TV is already muted." << std::endl;
}

main.cpp

#include <iostream>
using namespace std;
#include "state.h"
#include "remote.h"int main() {TVState* off = new MuteState;TVRemote remote(off);remote.pressOnButton();    // Turning on the TV.remote.pressOnButton();    // The TV is already on.remote.pressMuteButton();  // Muting the TV.remote.pressMuteButton();  // The TV is already muted.remote.pressOffButton();   // Turning off the TV.remote.pressOffButton();   // The TV is already off.remote.pressMuteButton();  // Cannot mute the TV when it's turned off.remote.pressOnButton();    // Turning on the TV.remote.pressMuteButton();  // Unmuting the TV.return 0;
}

在这里插入图片描述

相关文章:

【30】c++设计模式——>状态模式

状态模式概述 状态模式是一种行为型设计模式&#xff0c;它可以让一个对象在其内部状态发生变化时更改其行为。通过将每个状态封装成一个独立的类&#xff0c;我们可以使状态之间互相独立&#xff0c;并且使得状态的切换变得更加灵活、可扩展。&#xff08;多个状态之间可以相…...

中文编程开发语言编程实际案例:程序控制灯电路以及桌球台球室用这个程序计时计费

中文编程开发语言编程实际案例&#xff1a;程序控制灯电路以及桌球台球室用这个程序计时计费 上图为&#xff1a;程序控制的硬件设备电路图 上图为&#xff1a;程序控制灯的开关软件截图&#xff0c;适用范围比如&#xff1a;台球厅桌球室的计时计费管理&#xff0c;计时的时候…...

【python】高斯日记

题目&#xff1a; """ 题目描述&#xff1a; 高斯出生于1777年4月30日&#xff0c;记作1777-4-30。在此基础上&#xff0c;我们希望你写一个程序&#xff0c;给定一个数字n&#xff0c;表示从高斯出生的那天算起的第n天&#xff0c;输出这一天的具体日期。例如&…...

[论文笔记]MobileBERT

引言 今天带来一篇关于量化的论文MobileBERT,题目翻译过来是:一种适用于资源有限设备的紧凑型任务无关BERT模型。模型的简称是MobileBERT,意思是作者的这个BERT模型可以部署到手机端。 本篇工作,作者提出了MobileBERT用于压缩和加速BERT模型。与原始BERT一样,MobileBERT…...

【Spring Cloud】如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本

文章目录 1. 版本选择2. 用脚手架快速生成微服务的pom.xml3. 创建一个父工程4. 代码地址 本文描述如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本。 1. 版本选择 我们知道Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本选择一致性非常重…...

Power BI 傻瓜入门 1. 数据分析术语:Power BI风格

本章内容包括&#xff1a; 了解Power BI可以处理的不同类型的数据了解您的商业智能工具选项熟悉Power BI术语 数据无处不在。从你醒来的那一刻到你睡觉的时候&#xff0c;某个系统会代表你收集数据。即使在你睡觉的时候&#xff0c;也会产生与你生活的某些方面相关的数据。如…...

【C++和数据结构】位图和布隆过滤器

目录 一、位图 1、位图的概念 2、位图的实现 ①、基本结构 ②、set ③、reset&#xff1a; ④、test ⑤、问题&#xff1a; ⑥、位图优缺点及应用&#xff1a; ⑦、完整代码及测试 二、布隆过滤器 1、布隆过滤器的提出 2、布隆过滤器的实现 ①、基本结构 ②…...

Mybatis分页

本文主要讲解Mybatis分页相关的技术分享&#xff0c;如果觉得不错的话&#xff0c;就点个赞吧。。。。 Mybatis分页主要有2种类型&#xff1a; 一、物理分页&#xff1a; 1、定义&#xff1a; 物理分页是在数据库层面进行的分页&#xff0c;即通过SQL语句直接从数据库中查询…...

手写SVG图片

有时候QT中可能会需要一些简单的SVG图片,但是网上的质量参差不齐,想要满意的SVG图片,我们可以尝试直接手写的方法. 新建文本文档,将以下代码复制进去,修改后缀名为.svg,保存 <?xml version"1.0" encoding"utf-8"?> <svg xmlns"http://www…...

LVS负载均衡及LVS-NAT模式

一、集群概述 1.1 集群的背景 集群定义&#xff1a;为解决某个特定问题将多个计算机组合起来形成一个单系统 集群目的&#xff1a;为了解决系统的性能瓶颈 集群发展历史&#xff1a; 垂直扩展&#xff1a;向上扩展&#xff0c;增加单个机器的性能&#xff0c;即升级硬件 水…...

【Java集合类面试八】、 介绍一下HashMap底层的实现原理

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 介绍一下HashMap底层的…...

linux 安装操作 redis

1、redis概述和安装 1.1、安装redis 1. 下载redis 地址 https://download.redis.io/releases/ 2. 将 redis 安装包拷贝到 /opt/ 目录 3. 解压 tar -zvxf redis-6.2.1.tar.gz4. 安装gcc yum install gcc5. 进入目录 cd redis-6.2.16. 编译 make7. 执行 make install 进…...

博客后台模块续更(五)

十一、后台模块-菜单列表 菜单指的是权限菜单&#xff0c;也就是一堆权限字符串 1. 查询菜单 1.1 接口分析 需要展示菜单列表&#xff0c;不需要分页。可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询。菜单要按照父菜单id和orderNum进行排序 请求方式 请求路径…...

手写一个PrattParser基本运算解析器4: 简述iOS的编译过程

点击查看 基于Swift的PrattParser项目 iOS项目的编译过程与PrattParser解析器 前面三篇我们看到了PrattParser解析器的工作原理, 工作过程, 我们了解到PrattParser解析器实际上是模拟了编译过程中的 词法分析 、语法分析 、语义分析 、 中间代码生成 这几个编译前端过程. 那么P…...

【Java集合类面试六】、 HashMap有什么特点?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;HashMap有什么特点&…...

基于LSTM的天气预测 - 时间序列预测 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 机器学习大数据分析项目 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/po…...

SpringBoot AOP + Redis 延时双删功能实战

一、业务场景 在多线程并发情况下&#xff0c;假设有两个数据库修改请求&#xff0c;为保证数据库与redis的数据一致性&#xff0c;修改请求的实现中需要修改数据库后&#xff0c;级联修改Redis中的数据。 请求一&#xff1a;A修改数据库数据 B修改Redis数据 请求二&#xff…...

【Java集合类面试七】、 JDK7和JDK8中的HashMap有什么区别?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;JDK7和JDK8中的HashMap有…...

el-tree 获取过滤后的树结构

正常来说element框架应该返回的&#xff0c;但实际上没有&#xff0c;只能自己处理了 递归处理&#xff0c;思路就是赋值&#xff0c;如果是自己过滤到的数据就push进去&#xff0c;不是就不要 let newCheckTree [] let tree get_tree(treeData,newCheckTree); //获取过滤…...

Windows连接SFTP服务

最近有个新需求需要通过SFTP方式连接到一个FTP中下载相关内容 1.使用命令行方式 在cmd中使用如下命令 sftp -P [port] [username]ip #示例 sftp -P 666 ftp123.123.123.123然后弹出的提示输入yes&#xff0c;再输入密码就可以了。 2.使用资源管理器方式 普通FTP可以使用资源…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...