重温设计模式--状态模式

文章目录

  • 状态模式(State Pattern)概述
  • 状态模式UML图
  • 作用:
  • 状态模式的结构
    • 环境(Context)类:
    • 抽象状态(State)类:
    • 具体状态(Concrete State)类:
  • C++ 代码示例1
  • C++示例代码2
  • 应用场景
    • 游戏开发领域
    • 图形用户界面(GUI)系统
    • 工作流系统和业务流程管理
    • 网络协议和通信系统

状态模式(State Pattern)概述

定义:
状态模式是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为。就好像对象看起来修改了它的类一样,通过将不同状态对应的行为封装到不同的状态类中,让一个对象在不同的状态下可以表现出不同的行为,而这些行为的切换是由对象的状态变化来驱动的。

状态模式UML图

在这里插入图片描述

作用:

提高代码的可维护性和可扩展性:当一个对象有多种状态,且每种状态下行为差异较大时,如果使用大量的条件判断语句(如if-else或者switch语句)来处理不同状态下的行为,代码会变得复杂且难以维护。而状态模式把不同状态的行为分散到各个对应的状态类中,后续添加新状态或者修改某个状态下的行为就比较方便,只需对相应的状态类进行操作,不会影响到其他部分的代码。
符合开闭原则:对扩展开放,对修改关闭。例如在一个游戏角色有多种状态(站立、行走、攻击等)的场景中,若要新增一种 “跳跃” 状态以及对应的行为,只需要新增一个 “跳跃” 状态类实现相关行为逻辑,而不用去大规模修改原有的代码结构,原有的状态类和使用状态的对象代码都可以保持相对稳定。
增强代码的可读性:不同状态下的行为逻辑清晰地封装在各自的状态类中,阅读代码时可以更直观地了解每个状态对应的具体操作,相比于把所有状态相关行为混杂在一个类里的写法,结构更加清晰明了。

状态模式的结构

环境(Context)类:

它定义了客户端感兴趣的接口,并且维护一个具体状态类的实例,这个实例代表了当前对象所处的状态。环境类的行为会受到其内部状态对象的影响,它会将请求委托给当前状态对象来处理。

抽象状态(State)类:

它定义了一个接口,这个接口包含了那些在不同具体状态下对象可能执行的方法,所有的具体状态类都要实现这个抽象状态类所定义的接口,来提供各自状态下的具体行为逻辑。

具体状态(Concrete State)类:

实现了抽象状态类中定义的接口,针对具体的某一种状态,提供了该状态下相应行为的具体实现。每个具体状态类实现的行为会根据具体业务需求而不同,当环境类的状态切换到某个具体状态时,环境类发出的请求就会由对应的这个具体状态类来处理。

C++ 代码示例1

以下以一个简单的电梯控制系统为例来展示状态模式的代码实现。电梯有几种不同的状态,比如静止、上升、下降等,每种状态下对于外部的请求(如按楼层按钮等)会有不同的响应行为。

#include <iostream>// 抽象状态类
class ElevatorState
{
public:virtual void open() = 0;virtual void close() = 0;virtual void run() = 0;virtual void stop() = 0;
};// 具体状态类:静止状态
class StoppedState : public ElevatorState 
{
public:void open() override{std::cout << "电梯门打开,当前处于静止状态。" << std::endl;}void close() override {std::cout << "电梯门关闭,当前处于静止状态,准备运行。" << std::endl;}void run() override{std::cout << "电梯从静止状态开始运行。" << std::endl;}void stop() override {std::cout << "电梯已经处于静止状态,无需再次停止。" << std::endl;}
};// 具体状态类:上升状态
class RisingState : public ElevatorState 
{
public:void open() override{std::cout << "电梯正在上升,不能开门。" << std::endl;}void close() override {std::cout << "电梯正在上升,门已关闭。" << std::endl;}void run() override{std::cout << "电梯继续上升。" << std::endl;}void stop() override{std::cout << "电梯上升过程中停止。" << std::endl;// 假设停止后切换到静止状态,可以在这里做相应状态切换逻辑,比如通知环境类切换状态}
};// 具体状态类:下降状态
class FallingState : public ElevatorState 
{
public:void open() override {std::cout << "电梯正在下降,不能开门。" << std::endl;}void close() override{std::cout << "电梯正在下降,门已关闭。" << std::endl;}void run() override {std::cout << "电梯继续下降。" << std::endl;}void stop() override{std::cout << "电梯下降过程中停止。" << std::endl;// 同样,停止后可考虑切换状态逻辑}
};// 环境类:电梯
class Elevator
{
private:ElevatorState* currentState;
public:Elevator(){currentState = new StoppedState();}void setCurrentState(ElevatorState* state) {currentState = state;}void open(){currentState->open();}void close(){currentState->close();}void run() {currentState->run();}void stop() {currentState->stop();}
};int main()
{Elevator elevator;elevator.open();elevator.close();elevator.run();elevator.stop();RisingState risingState;elevator.setCurrentState(&risingState);elevator.open();elevator.close();elevator.run();elevator.stop();return 0;
}

C++示例代码2

#include<iostream>
#include<list>
#include<string>
using namespace std;
class Andy;//男主
class State//状态
{
public:string m_satedes;//描述当前的状态
public:virtual void Fbegin(){};//前期状态virtual void Fmid(){};//中期状态virtual void Fend(){};//末期状态virtual void CurrentState(Andy*p_andy){};//调用当前状态,统一的接口,然后各个状态子类去调用自己的函数
};
class Andy
{
private:State *m_state;  //目前状态int m_years;      //时间
public:Andy(State *state): m_state(state), m_years(0) {}~Andy() { delete m_state; }int GetYears() { return m_years; }void SetYears(int years) { m_years = years; }void SetState(State *state) { delete m_state; m_state = state; }void GetState() { m_state->CurrentState(this); }
};//服刑末期
class State_End:public State
{
public:State_End(){m_satedes = "挖洞逃出来了";}void FEnd(Andy *p_andy){cout<<"第"<<p_andy->GetYears()<<"年"<<m_satedes<<endl;}void CurrentState(Andy *p_andy){FEnd(p_andy);}
};//服刑中期
class State_Mid:public State
{
public:State_Mid(){m_satedes = "服刑中期,每天帮监狱长做假账,顺便开始夜里挖洞";}void FMid(Andy *p_andy){if(p_andy->GetYears()<28){cout<<"第"<<p_andy->GetYears()<<"年"<<m_satedes<<endl;}else{p_andy->SetState(new State_End());p_andy->GetState();}}void CurrentState(Andy *p_andy){FMid(p_andy);}
};//服刑前期
class State_begin:public State
{
public:State_begin(){m_satedes = "男主Andy刚进监狱,处处受人欺负";}void Fbegin(Andy *p_andy){if(p_andy->GetYears()<5){cout<<"第"<<p_andy->GetYears()<<"年"<<m_satedes<<endl;}else{p_andy->SetState(new State_Mid());p_andy->GetState();}}void CurrentState(Andy *p_andy){Fbegin(p_andy);}
};int main()
{Andy *p = new Andy(new (State_begin));for(int i = 1; i < 40; ++i){p->SetYears(i);p->GetState();}delete p;return 0;
}

应用场景

游戏开发领域

角色状态管理:游戏中的角色通常有多种状态,如站立、行走、奔跑、跳跃、攻击、受伤、死亡等。使用状态模式可以为每个状态创建一个单独的类,在这些类中实现角色在该状态下的行为,如移动速度、动画播放、可执行的操作等。例如,当角色处于攻击状态时,其移动速度可能会降低,并且会播放攻击动画,同时能够触发攻击相关的逻辑,如伤害计算。
游戏场景状态切换:游戏场景也可以有不同的状态,像游戏的主菜单场景、游戏进行中的场景、暂停场景、游戏结束场景等。每个场景状态都有自己的一套显示内容、交互逻辑和更新机制。通过状态模式,可以方便地在不同场景状态之间切换,并且清晰地管理每个状态下的资源加载、渲染和事件处理。

图形用户界面(GUI)系统

窗口状态管理:一个窗口可能有多种状态,如最小化、最大化、正常、隐藏等。在不同状态下,窗口的显示方式、对用户操作的响应等都不同。利用状态模式,可以将每个状态对应的行为封装到相应的状态类中。例如,当窗口处于最小化状态时,它可能只在任务栏显示一个图标,并且点击图标时的操作(如恢复窗口大小)与窗口处于正常状态时的操作(如拖动边框改变大小)是不同的。
按钮状态控制:按钮有正常、鼠标悬停、按下等状态。在不同状态下,按钮的外观(如颜色、样式)和行为(如触发的事件)不同。状态模式可以让开发者轻松地定义每个状态下按钮的渲染逻辑和事件响应逻辑,使得按钮的状态管理更加清晰和易于维护。

工作流系统和业务流程管理

订单处理流程:在电商系统中,订单有多种状态,如已创建、已付款、已发货、已签收、已退款等。每个状态下的订单处理逻辑不同,例如在 “已付款” 状态下,系统会通知仓库准备发货;在 “已发货” 状态下,系统会提供物流信息查询等服务。通过状态模式,可以把订单在不同状态下的处理逻辑封装在对应的状态类中,方便业务流程的扩展和维护。
审批流程:企业中的审批流程也存在多种状态,如提交审批、部门主管审批中、高层领导审批中、审批通过、审批拒绝等。对于每个状态,都有相应的操作和流转规则,比如在 “部门主管审批中” 状态下,部门主管可以查看申请内容并进行审批操作,审批通过后状态会切换到 “高层领导审批中”。使用状态模式可以清晰地实现这种复杂审批流程的状态管理和操作逻辑。

网络协议和通信系统

TCP 连接状态管理:在 TCP 协议中,连接有多种状态,如 LISTEN(监听)、SYN - SENT(同步已发送)、SYN - RECEIVED(同步收到)、ESTABLISHED(已建立)、FIN - WAIT - 1(终止等待 1)等。在不同状态下,网络设备(如服务器和客户端)的行为和数据处理方式不同。状态模式可以用于实现 TCP 连接状态的管理,将每个状态对应的数据包处理、连接维护等操作封装在相应的状态类中,使得网络通信的状态处理更加清晰和可靠。
设备通信状态:在物联网系统中,设备之间的通信可能会出现多种状态,如连接正常、连接中断、数据传输中、等待响应等。对于每种状态,可以使用状态模式来定义设备在该状态下的通信行为,如重新连接策略、数据缓存和发送方式等,以确保设备之间的通信稳定和高效。

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

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

相关文章

Java代码覆盖率super-jacoco

项目流程 项目架构 部署步骤 注意&#xff1a;一定要用Linux服务器部署&#xff0c;不要用Windows 准备Linux服务器环境 安装好JDK1.8 安装好git 安装和配置好Maven3.6&#xff0c;或3.6以下 安装MySQL数据库&#xff08;尽量不用8版本&#xff0c;就用5.7、5.8版本&#xf…

Day1 苍穹外卖前端 Vue基础、Vue基本使用方式、Vue-router、Vuex、TypeScript

目录 1.VUE 基础回顾 1.1 基于脚手架创建前端工程 1.1.1 环境要求 1.1.2 脚手架创建项目 1.1.3 工程结构 1.1.4 启动前端服务 1.2 vue基本使用方式 1.2.1 vue 组件 1.2.2 文本插值 1.2.3 属性绑定 1.2.4 事件绑定 1.2.5 双向绑定 1.2.6 条件渲染 1.2.7 跨域问题 1.2.8 axios 1.…

重温设计模式--中介者模式

中介者模式介绍 定义&#xff1a;中介者模式是一种行为设计模式&#xff0c;它通过引入一个中介者对象来封装一系列对象之间的交互。中介者使得各个对象之间不需要显式地相互引用&#xff0c;从而降低了它们之间的耦合度&#xff0c;并且可以更方便地对它们的交互进行管理和协调…

Redis篇--常见问题篇7--缓存一致性2(分布式事务框架Seata)

1、概述 在传统的单体应用中&#xff0c;事务管理相对简单&#xff0c;通常使用数据库的本地事务&#xff08;如MySQL的BEGIN和COMMIT&#xff09;来保证数据的一致性。然而&#xff0c;在微服务架构中&#xff0c;由于每个服务都有自己的数据库&#xff0c;跨服务的事务管理变…

如何评估一个股票API接口

评估一个股票 API 接口的质量&#xff0c;可以从以下几个方面进行&#xff1a; 数据准确性 行情数据&#xff1a;实时价格、历史价格、成交量、成交额等数据应与证券交易所或权威金融数据提供商的官方数据高度一致&#xff0c;确保没有明显的错误。财务数据&#xff1a;企业的…

某集团GIF动态验证码识别

注意&#xff0c;本文只提供学习的思路&#xff0c;严禁违反法律以及破坏信息系统等行为&#xff0c;本文只提供思路 如有侵犯&#xff0c;请联系作者下架 本文识别已同步上线至OCR识别网站&#xff1a; http://yxlocr.nat300.top/ocr/other/16 最近某集团更新了验证码&#x…

数据库系统原理:数据恢复与备份策略

3.1可行性分析 开发者在进行开发系统之前&#xff0c;都需要进行可行性分析&#xff0c;保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该《数据库系统原理》课程平台所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识…

CPU算法分析LiteAIServer裸土检测算法如何应用在农田科学管理中?

农田是农业生产的基础&#xff0c;是保障国家粮食安全和农业可持续发展的关键。随着人口增长和城市化进程的加快&#xff0c;农田保护和治理面临着前所未有的挑战。如今农田土壤依旧面临着巨大挑战&#xff1a; 1、‌土壤侵蚀‌&#xff1a;长期的风蚀、水蚀等自然因素&#x…

Marscode AI辅助编程

直接使用Marscode的云服务来开发&#xff0c;也是很方便的&#xff0c;不用担心配置环境的问题&#xff0c;很适合初步学习&#xff0c;在任何设备都能开发。 番茄钟 请你基于html、tailwind css和javascript&#xff0c;帮我设计一个“番茄时钟”。要求UI简洁美观大方&#x…

Debian 12 安装配置 fail2ban 保护 SSH 访问

背景介绍 双十一的时候薅羊毛租了台腾讯云的虚机, 是真便宜, 只是没想到才跑了一个月, 系统里面就收集到了巨多的 SSH 恶意登录失败记录. 只能说, 互联网真的是太不安全了. 之前有用过 fail2ban 在 CentOS 7 上面做过防护, 不过那已经是好久好久之前的故事了, 好多方法已经不…

idea2024创建JavaWeb项目以及配置Tomcat详解

今天呢&#xff0c;博主的学习进度也是步入了JavaWeb&#xff0c;目前正在逐步杨帆旗航&#xff0c;迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正…

Canoe E2E校验自定义Checksum算法

文章目录 一、添加 DBC文件二、导入要仿真的ECU节点三、编写 CAPL脚本1. 创建 .can 文件2. 设置counter递增3. 设置 CRC 算法&#xff0c;以profile01 8-bit SAE J1850 CRC校验为例 四、开始仿真五、运行结果CRC在线校验 当E2E的 CRC算法非常规算法&#xff0c;则需要自己编写代…

PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程

PyTorch 神经网络回归&#xff08;Regression&#xff09;任务&#xff1a;关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合&#xff0c;具体演示了从数据准备到模型训练和可视化的完整过程。首先&#xff0c;利用一维线性空间生成带噪…

【uni-app】2025最新uni-app一键登录保姆级教程(包含前后端获取手机号方法)(超强避坑指南)

前言&#xff1a; 最近在配置uni-app一键登录时遇到了不少坑&#xff0c;uni-app的配套文档较为混乱&#xff0c;并且有部分更新的内容也没有及时更改在文档上&#xff0c;导致部分开发者跟着uni-app配套文档踩坑&#xff01;而目前市面上的文章质量也层次不齐&#xff0c;有的…

干货分享:ISO 20000认证的适用范围、认证资料清单、认证流程等问题详解

编辑&#xff1a;石芸姗 审核&#xff1a;贺兆普 在当今这个数字化时代&#xff0c;信息技术&#xff08;IT&#xff09;已成为企业运营与发展的核心驱动力。随着技术的不断进步和业务需求的日益复杂&#xff0c;企业对IT服务的质量、效率及安全性提出了更高要求。 信息技术服…

Element-plus表格使用总结

这里我使用的是Vue工程进行开发学习&#xff0c;安装需要通过包管理器进行下载 npm install element-plus --save 然后在main.js中配置文件即可使用&#xff0c;如果在引入index.css时没有提示&#xff0c;无需担心&#xff0c;直接写index.css即可导入样式。 Table表格 表格…

CNN和Transfomer介绍

文章目录 CNN和Transfomer介绍CNN和Transfomer的区别1. **基本概念**2. **数据处理方式**3. **模型结构差异**4. **应用场景区别** 自注意力机制1. **自注意力机制的概念**2. **自注意力机制的实现步骤**3. **自注意力机制的优势** Transformer结构组成1. **多头注意力层&#…

如何解决 ‘adb‘ 不是内部或外部命令,也不是可运行的程序或批处理文件的问题

在cmd中输入 adb &#xff0c;显示 ‘adc‘ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件的问题 解决办法&#xff1a;在环境变量中添加adb所在的路径 1、找到 adb.exe 的所在的文件路径&#xff0c;一般在 Android 安装目录下 \sdk\platform-tools\adb.exe…

数据结构---------二叉树前序遍历中序遍历后序遍历

以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例&#xff0c;包括递归和非递归&#xff08;借助栈实现&#xff09;两种方式&#xff1a; 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…

网络架构与IP技术:4K/IP演播室制作的关键支撑

随着科技的不断发展&#xff0c;广播电视行业也在不断迭代更新&#xff0c;其中4K/IP演播室技术的应用成了一个引人注目的焦点。4K超高清技术和IP网络技术的结合&#xff0c;不仅提升了节目制作的画质和效果&#xff0c;还为节目制作带来了更高的效率和灵活性。那么4K超高清技术…