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

状态模式——C++实现

目录

1. 状态模式简介

2. 代码示例

3. 单例状态对象

4. 状态模式与策略模式的辨析


1. 状态模式简介

状态模式是一种行为型模式

状态模式的定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

通俗的说就是一个对象在不同的状态下拥有不同的行为。对象可以拥有多个不同的状态,不同状态下调用同一个接口会产生不同的行为。状态模式通过把状态封装成类,可以很好地维护一个对象的不同状态,并且方便地扩展新的状态。


举个例子:

假如在游戏程序中,要模拟一个怪物。怪物的总血量为100,当血量大于50时,怪物处于亢奋状态,怪物受击时会进行反击;当血量小于等于50时,怪物处于恐慌状态,受击时会选择逃跑。

在这个例子中,怪物具有明确的状态,并且在不同的状态下,同一个接口会有不同的行为。这种情况下就非常适合使用状态模式。

2. 代码示例

下面的代码实现了上文提到的怪物模拟程序:

#if 1#include <iostream>using namespace std;class Monster;
class State
{
protected:Monster* monster_;
public:virtual ~State() {}State(Monster* m) :monster_(m) {}virtual void attacked(int damage) = 0;
};class Monster
{
public:Monster();~Monster();void setState(State* state){curState = state;}State* getExcitedState(){return excitedState;}State* getHorrifiedState(){return horrifiedState;}State* getDeadState(){return deadState;}void attacked(int damage){curState->attacked(damage);}int getCurHealth()const { return health; }int reduceHealth(int damage){health -= damage;health = max(0, health);return health;}
private:State* curState;State* excitedState;State* horrifiedState;State* deadState;int health = 100;
};class ExcitedState : public State
{
public:using State::State;void attacked(int damage){cout << "怪物的当前状态为 ExcitedState" << endl;cout << "怪物尝试反击" << endl;cout << "怪物受到" << damage << "点伤害" << endl;int curHealth = monster_->reduceHealth(damage);cout << "怪物剩余血量:" << curHealth << endl;if (curHealth <= 50){monster_->setState(monster_->getHorrifiedState());cout << "怪物进入 HorrifiedState" << endl;}}
};class HorrifiedState : public State
{
public:using State::State;void attacked(int damage){cout << "怪物的当前状态为 HorrifiedState" << endl;cout << "怪物尝试逃跑" << endl;cout << "怪物受到" << damage << "点伤害" << endl;int curHealth = monster_->reduceHealth(damage);cout << "怪物剩余血量:" << curHealth << endl;if (curHealth <= 0){monster_->setState(monster_->getDeadState());cout << "怪物进入 DeadState" << endl;}}
};class DeadState : public State
{
public:using State::State;void attacked(int damage){cout << "怪物的当前状态为 DeadState" << endl;cout << "怪物已经死亡, 无法受到伤害" << endl;}
};Monster::Monster()
{excitedState = new ExcitedState(this);horrifiedState = new HorrifiedState(this);deadState = new DeadState(this);curState = excitedState;
}Monster::~Monster()
{delete excitedState;delete horrifiedState;delete deadState;	
}int main()
{Monster monster;monster.attacked(0);cout << "---------------------" << endl;monster.attacked(30);cout << "---------------------" << endl;monster.attacked(40);cout << "---------------------" << endl;monster.attacked(80);cout << "---------------------" << endl;monster.attacked(100);cout << "---------------------" << endl;return 0;
}#endif 

运行结果如下图所示:

 

代码中增加了死亡状态,当怪物血量小于0时进入了死亡状态。

采用状态模式可以很方便地扩展,增加新的状态会非常便捷。

3. 单例状态对象

当状态对象不含有自身内部的状态时,可以考虑将状态类实现成单例模式

4. 状态模式与策略模式的辨析

状态模式策略模式的结构十分类似,两种模式的差别在于它们的目的不同。

  • 对于状态模式来说,可以将对象的一组行为封装在一个状态对象中,context对象(拥有状态的对象)的行为可以随时通过切换不同的状态对象而改变。随着时间的流逝,当前的状态也在多个状态对象中发生改变,以反映context内部的状态,context的行为也会改变。但是对于客户端代码对于context的状态对象可以毫无察觉,不需要了解。context的状态切换是在其内部进行的,客户端代码感知不到客户端只能感受到context的行为产生了变化,而无需了解其当前的状态是怎么样的
  • 对于策略模式来说,通常需要客户端主动指定context当前所需要的策略对象是哪一个。策略模式允许在程序运行过程中改变策略,但是对于某个context对象来说,通常只有一个当前最适合的策略。策略的切换是通过客户端代码主动发起的

相关文章:

状态模式——C++实现

目录 1. 状态模式简介 2. 代码示例 3. 单例状态对象 4. 状态模式与策略模式的辨析 1. 状态模式简介 状态模式是一种行为型模式。 状态模式的定义&#xff1a;状态模式允许对象在内部状态改变时改变它的行为&#xff0c;对象看起来好像修改了它的类。 通俗的说就是一个对象…...

3.观察者模式(Observer)

组件协作模式 现代软件专业分工之后的第一个结果是 “框架与应用程序的划分”,“组件协作” 模式通过晚期绑定&#xff0c;来实现框架与应用程序直接的松耦合&#xff0c;是二者之间协作时常用的模式 典型模式 Template Method Strategy Observer /Event 动机&#xff08;M…...

Kotlin判空辅助工具

1&#xff09;?.操作符 //执行逻辑 if (person ! null) {person.doSomething() } //表达式 person?.doSomething() 2&#xff09;?:操作符 //执行逻辑 val c if (a ! null) {a } else {b } //表达式 val c a ?: b 3&#xff09;!!表达式 var message: String? &qu…...

Electron学习笔记,安装环境(1)

1、支持win7的Electron 的版本是18&#xff0c;这里node.js用的是14版本&#xff08;node-v14.21.3-x86.msi&#xff09;云盘有安装包 Electron 18.x (截至2023年仍在维护中): Chromium: 96 Node.js: 14.17.0 2、安装node环境&#xff0c;node-v14.21.3-x86.msi双击运行选择安…...

将 OneLake 数据索引到 Elasticsearch - 第 1 部分

作者&#xff1a;来自 Elastic Gustavo Llermaly 学习配置 OneLake&#xff0c;使用 Python 消费数据并在 Elasticsearch 中索引文档&#xff0c;然后运行语义搜索。 OneLake 是一款工具&#xff0c;可让你连接到不同的 Microsoft 数据源&#xff0c;例如 Power BI、Data Activ…...

【C++】STL介绍 + string类使用介绍 + 模拟实现string类

目录 前言 一、STL简介 二、string类 1.为什么学习string类 2.标准库中的string类 3.auto和范围for 4.迭代器 5.string类的常用接口说明 三、模拟实现 string类 前言 本文带大家入坑STL&#xff0c;学习第一个容器string。 一、STL简介 在学习C数据结构和算法前&#xff0c;我…...

Hive:基本查询语法

和oracle一致的部分 和oracle不一样的部分 排序 oracle中,在升序排序中&#xff0c;NULL 值被视为最大的值&#xff1b;在降序排序中&#xff0c;NULL 值被视为最小的值。 在MySQL中&#xff0c;NULL 被视为小于任何非空值。 在Hive中, NULL是最小的; Hive除了可以用order…...

日志收集Day008

1.zk集群优化 修改zookeeper的堆内存大小&#xff0c;一般情况下&#xff0c;生产环境给到2G足以&#xff0c;如果规模较大可以适当调大到4G。 (1)配置ZK的堆内存 vim /app/softwares/zk/conf/java.env export JAVA_HOME/sortwares/jdk1.8.0_291 export JVMFLAGS"-Xms2…...

【解决方案】VMware虚拟机adb连接宿主机夜神模拟器

1、本机&#xff08;宿主机&#xff0c;系统windows10&#xff09;ip为192.168.31.108 2、运行模拟器后本机cmd查看端口为62026 3、VMware虚拟机&#xff08;系统&#xff0c;kali&#xff09;adb连接192.168.31.108:62026报错 failed to connect to 192.168.31.108:16416: Co…...

基于金融新闻的大型语言模型强化学习在投资组合管理中的应用

“Financial News-Driven LLM Reinforcement Learning for Portfolio Management” 论文地址&#xff1a;https://arxiv.org/pdf/2411.11059 摘要 本研究探索了如何通过将大语言模型&#xff08;LLM&#xff09;支持的情感分析融入强化学习&#xff08;RL&#xff09;中&#…...

脚本运行禁止:npm 无法加载文件,因为在此系统上禁止运行脚本

问题与处理策略 1、问题描述 npm install -D tailwindcss执行上述指令&#xff0c;报如下错误 npm : 无法加载文件 D:\nodejs\npm.ps1&#xff0c;因为在此系统上禁止运行脚本。 有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_…...

借DeepSeek-R1东风,开启创业新机遇

DeepSeek-R1的崛起 DeepSeek-R1的推出引发了广泛关注&#xff0c;在AI领域引起了一阵旋风。作为新一代的智能模型&#xff0c;它在多项任务中表现出了卓越的能力。普通人可以借助这个强大的工具&#xff0c;开启属于自己的创业之路&#xff0c;抓住时代带来的机遇。 内容创作…...

C# lock使用详解

总目录 前言 在 C# 多线程编程中&#xff0c;lock 关键字是一种非常重要的同步机制&#xff0c;用于确保同一时间只有一个线程可以访问特定的代码块&#xff0c;从而避免多个线程同时操作共享资源时可能出现的数据竞争和不一致问题。以下是关于 lock 关键字的详细使用介绍。 一…...

简易CPU设计入门:控制总线的剩余信号(四)

项目代码下载 请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 CSDN文章&#xff1a;下载本项目代码 上述链接为本项目…...

使用 lock4j-redis-template-spring-boot-starter 实现 Redis 分布式锁

在分布式系统中&#xff0c;多个服务实例可能同时访问和修改共享资源&#xff0c;从而导致数据不一致的问题。为了解决这个问题&#xff0c;分布式锁成为了关键技术之一。本文将介绍如何使用 lock4j-redis-template-spring-boot-starter 来实现 Redis 分布式锁&#xff0c;从而…...

22_解析XML配置文件_List列表

解析XML文件 需要先 1.【加载XML文件】 而 【加载XML】文件有两种方式 【第一种 —— 使用Unity资源系统加载文件】 TextAsset xml Resources.Load<TextAsset>(filePath); XmlDocument doc new XmlDocument(); doc.LoadXml(xml.text); 【第二种 —— 在C#文件IO…...

编译器gcc/g++ --【Linux基础开发工具】

文章目录 一、背景知识二、gcc编译选项1、预处理(进行宏替换)2、编译&#xff08;生成汇编&#xff09;3、汇编&#xff08;生成机器可识别代码&#xff09;4、链接&#xff08;生成可执行文件或库文件&#xff09; 三、动态链接和静态链接四、静态库和动态库1、动静态库2、编译…...

58.界面参数传递给Command C#例子 WPF例子

界面参数的传递&#xff0c;界面参数是如何从前台传送到后台的。 param 参数是从界面传递到命令的。这个过程通常涉及以下几个步骤&#xff1a; 数据绑定&#xff1a;界面元素&#xff08;如按钮&#xff09;的 Command 属性绑定到视图模型中的 RelayCommand 实例。同时&#x…...

games101-(5/6)

光栅化 投影完成之后&#xff0c;视图区域被确定在从[-1,1]的单位矩阵中&#xff0c;下一步就是光栅化 长宽比&#xff1a;ratio 垂直的可视角度&#xff1a;fild-of-view 可以看到的y 轴的范围&#xff0c;角度越小 越接近正交投影 屏幕坐标系 、 将多边形转化成像素 显示…...

人工智能在计算机视觉中的应用与创新发展研究

一、引言 1.1 研究背景与意义 1.1.1 研究背景 在当今数字化与智能化飞速发展的时代&#xff0c;人工智能已成为推动各领域变革的核心力量&#xff0c;而计算机视觉作为人工智能领域中极具活力与潜力的重要分支&#xff0c;正发挥着日益关键的作用。计算机视觉旨在赋予计算机…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

python基础语法Ⅰ

python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器&#xff0c;来进行一些算术…...

react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)

之前都是使用react-pdf来渲染pdf文件&#xff0c;这次有个需求是要兼容xp环境&#xff0c;xp上chrome最高支持到49&#xff0c;虽然说iframe或者embed都可以实现预览pdf&#xff0c;但为了后续的定制化需求&#xff0c;还是需要使用js库来渲染。 chrome 49测试环境 能用的测试…...