状态模式——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对象来说,通常只有一个当前最适合的策略。策略的切换是通过客户端代码主动发起的

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

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

相关文章

Word 中实现方框内点击自动打 √ ☑

注&#xff1a; 本文为 “Word 中方框内点击打 √ ☑ / 打 ☒” 相关文章合辑。 对第一篇增加了打叉部分&#xff0c;第二篇为第一篇中方法 5 “控件” 实现的详解。 在 Word 方框内打 √ 的 6 种技巧 2020-03-09 12:38 使用 Word 制作一些调查表、检查表等&#xff0c;通常…

利用 Three.js 实现 3D 粒子正方体效果

在这篇文章中&#xff0c;我将向大家展示如何使用 Three.js 创建一个带有粒子的 3D 正方体效果。通过这段代码&#xff0c;我们将能够在浏览器中渲染一个 3D 正方体形状&#xff0c;并且该正方体内部填充了大量粒子&#xff08;可视化效果&#xff09;。你可以通过鼠标控制视角…

DRF开发避坑指南01

在当今快速发展的Web开发领域&#xff0c;Django REST Framework&#xff08;DRF&#xff09;以其强大的功能和灵活性成为了众多开发者的首选。然而&#xff0c;错误的使用方法不仅会导致项目进度延误&#xff0c;还可能影响性能和安全性。本文将从我个人本身遇到的相关坑来给大…

ES设置证书和创建用户,kibana连接es

1、启动好es 2、进入es容器 docker exec -it es /bin/bash 3、生成ca证书 ./bin/elasticsearch-certutil ca 注&#xff1a;两个红方框位置直接回车 4、生成cert证书 ./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 注&#xff1a;前两个红框直接回车&am…

一位前端小白的2024总结

目录 简要 一、迷茫点的解决 &#xff08;1&#xff09;前端领域该怎么学&#xff1f; &#xff08;2&#xff09;旧技术还需要学吗&#xff1f; &#xff08;3&#xff09;我该学些什么&#xff1f; 二、折磨点的解决 &#xff08;1&#xff09;学技术成果回报太慢怎么…

数据分析学习路线

阶段 1&#xff1a;数学与统计基础 1.1 数学基础 数据分析涉及大量的数学知识&#xff0c;尤其是统计学。虽然你不需要成为数学专家&#xff0c;但一些基本的数学概念对你理解数据分析非常重要。 线性代数&#xff1a; 矩阵运算&#xff1a;理解矩阵乘法、求逆等操作。特征值…

python爬虫 爬取站长素材 (图片)(自学6)

安装 &#xff1a;lxml 地址 &#xff1a; Installing lxml pip install lxml 或者 sudo pip install lxml 下面开始 写代码 下载 站长素材的图片 import urllib.requestfrom lxml import etreeimport osdef create_request(page):if(page 1):url "https://sc.chinaz.…

《OpenCV》——图像透视转换

图像透视转换简介 在 OpenCV 里&#xff0c;图像透视转换属于重要的几何变换&#xff0c;也被叫做投影变换。下面从原理、实现步骤、相关函数和应用场景几个方面为你详细介绍。 原理 实现步骤 选取对应点&#xff1a;要在源图像和目标图像上分别找出至少四个对应的点。这些对…

spring---@Pointcut表达式

spring语法 execution 方法表达式&#xff1a;execution(modifiers-pattern? ret-type-pattern declaring-type-pattern/name-pattern(param-pattern) throws-pattern?) 修饰符匹配(modifier-pattern?)&#xff1a;可以省略。代表匹配任意修饰符方法&#xff1b;或者显示…

第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

第十五届的题目在规定时间内做出了前5道&#xff0c;还有2道找时间再磨一磨。现在把做的一些思路总结如下&#xff1a; 题1&#xff1a;握手问题 问题描述 小蓝组织了一场算法交流会议&#xff0c;总共有 50人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例…

Linux - 五种常见I/O模型

I/O操作 (输入/输出操作, Input/Output) 是指计算机与外部设备就行数据交互的过程. 什么是外部设备: 如键盘, 鼠标, 硬盘, 网卡等. 五种常见的 I/O 模型: 阻塞 I/O非阻塞 I/O信号驱动 I/OI/O 多路复用异步 I/O 阻塞 I/O 阻塞 I/O 的特点: 当用户发起 I/O 请求后, 进程/线程就…

问题修复记录:Linux docker 部署 dify,无法调用宿主机本地服务

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

【UE5插件】RuntimeSpeechRecognizer

作用&#xff1a;语音识别 获取途径&#xff1a; Runtime Audio Importer | Fab 示例蓝图&#xff1a; 如何使用插件 |Georgy 开发文档 UE5.3 RuntimeSpeechRecognizer Streaming Example posted by gtreshchev | blueprintUE | PasteBin For Unreal Engine RuntimeSpeechReco…

2025年最新深度学习环境搭建:Win11+ cuDNN + CUDA + Pytorch +深度学习环境配置保姆级教程

本文目录 一、查看驱动版本1.1 查看显卡驱动1.2 显卡驱动和CUDA对应版本1.3 Pytorch和Python对应的版本1.4 Pytorch和CUDA对应的版本 二、安装CUDA三、安装cuDANN四、安装pytorch五、验证是否安装成功 一、查看驱动版本 1.1 查看显卡驱动 输入命令nvidia-smi可以查看对应的驱…

unity插件Excel转换Proto插件-ExcelToProtobufferTool

unity插件Excel转换Proto插件-ExcelToProtobufferTool **ExcelToProtobufTool 插件文档****1. 插件概述****2. 默认配置类&#xff1a;DefaultIProtoPathConfig****属性说明** **3. 自定义配置类****定义规则****示例代码** **4. 使用方式****4.1 默认路径****4.2 自定义路径**…

Web3 与数据隐私:如何让用户掌控个人信息

随着数字化时代的快速发展&#xff0c;互联网已经渗透到我们生活的方方面面&#xff0c;个人数据的收集与使用也变得越来越普遍。与此同时&#xff0c;数据隐私问题逐渐成为全球关注的焦点。传统的互联网平台通常将用户的数据存储在中心化的服务器上&#xff0c;这意味着平台拥…

HTML常用属性

HTML标签的常见属性包括许多不同的功能&#xff0c;可以为元素提供附加信息或控制元素的行为。以下是一些常见的属性及其解释&#xff1a; 1. src 描述&#xff1a;src&#xff08;source&#xff09;属性指定一个资源的路径&#xff0c;通常用于图像、音频、视频等标签。常见…

SQL Server 建立每日自动log备份的维护计划

SQLServer数据库可以使用维护计划完成数据库的自动备份&#xff0c;下面以在SQL Server 2012为例说明具体配置方法。 1.启动SQL Server Management Studio&#xff0c;在【对象资源管理器】窗格中选择数据库实例&#xff0c;然后依次选择【管理】→【维护计划】选项&#xff0…

基于 WPF 平台使用纯 C# 实现动态处理 json 字符串

一、引言 在当今的软件开发领域&#xff0c;数据的交换与存储变得愈发频繁&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;以其简洁、易读、便于解析和生成的特点&#xff0c;被广泛应用于各种应用程序中。在 W…

C++—21、C++ 中构造函数Constructors

一、什么是构造函数&#xff1f; 构造函数是一个特殊的方法&#xff0c;它在类每次实例化创建对象的时侯自动调用&#xff0c;用于初始化对象。 构造函数的名字必须与类名完全相同&#xff0c;并且没有返回类型&#xff0c;甚至连void也没有。 构造函数的目的是确保对象在创…