【深入浅出设计模式--状态模式】
深入浅出设计模式--状态模式
- 一、背景
- 二、问题
- 三、解决方案
- 四、 适用场景总结
- 五、后记
一、背景
状态模式是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。其与有限状态机的概念紧密相关,如下所示:

二、问题
在实际设计编码UI界面的工作中,有很多人应该都遇到过类似这样的场景:当鼠标移动或者点击某个标签、按钮等组件时,对应组件上会根据鼠标的状态进行不同的响应,比如颜色大小的变化。如果状态有很多种,那我们就会在代码中添加许多条件判断(if-else、switch),有时候可能一条语句中的条件多达十来个,出现bug的时候调试起来相当恶心。基于这个问题,下面使用状态模式逐步解决。
三、解决方案
- 首先在上下文类Context中定义改变状态的接口changeState,并聚合了指向当前状态的IState对象指针,changeState的参数即为new生成的具体状态类NormorlState等,调用paintTags函数时会调用当前状态类的doPaint函数进行该状态下的绘制操作。
- 接口状态类IState中提供了doPaint纯虚函数,每个具体状态类会继承并重写doPaint,在doPaint中可以调用setHoverState等函数对Context类对象的成员变量进行修改,同步状态与操作。
- 为了对每个状态类对象进行复用,采用单例模式提供GetInstance函数供Context调用。
类图如下:

- 上面的类结构中,因为每个具体状态类都是单例模式,提供除了名字不同之外相同的代码块,因此会有许多重复代码,因此想到在接口状态类IStateBase和具体状态类之间插入一个单例模板类IStateTemplate专门提供静态GetInstance函数,然后每个具体状态类对其继承和模板特化,这样在具体状态类中只需要实现doPaint函数即可。
- 各类达到高度凝练与抽象,每一层只专注某一功能的效果。后续如果有新加入一种状态,只需要特化IStateTemplate,然后重写doPaint函数即可,其他状态的代码无需修改,减少大量条件判断的同时也降低了出错的概率。
改进后的类图如下:

- 该模式下各类之间交互的时序图如下:

- Context类关键代码截图:

- State相关类关键代码截图:

四、 适用场景总结
- 如果对象需要根据自身当前状态(成员变量值)进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可使用状态模式。
- 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。
- 如果状态机只有很少的几个状态,或者很少发生改变,那么应用该模式可能会显得小题大作。
五、后记
以上所有内容均为原创,代码已上传至gayhub:
https://github.com/gangster-puppy/Design-Pattern.git
相关文章:
【深入浅出设计模式--状态模式】
深入浅出设计模式--状态模式 一、背景二、问题三、解决方案四、 适用场景总结五、后记 一、背景 状态模式是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。其与有限状态机的概念紧密相关&#x…...
Debezium系列之:Debezium Server在生产环境大规模应用详细的技术方案
Debezium系列之:Debezium Server在生产环境大规模应用详细的技术方案 一、需求背景二、Debezium Server实现技术三、技术方案流程四、生成接入配置五、新增数据库接入和删除数据库接入效果六、监控zookeeper节点程序七、新增数据库接入部署debezium server程序八、删除数据库接…...
Echart笔记
Echart笔记 柱状图带背景色的柱状图将X与Y轴交换制作为进度条 柱状图 带背景色的柱状图 将X与Y轴交换制作为进度条 //将X与Y轴交换制作为进度条 option { xAxis: {type: value,min:0,max:100,show:false,//隐藏x轴},yAxis: {type: category,data:[进度条],show:false,//隐…...
docker 笔记1
目录 1.为什么有docker ? 2.Docker 的核心概念 3.容器与虚拟机比较 3.1传统的虚拟化技术 3.2容器技术 3.3Docker容器的有什么作用? 3.4应用案例 4. docker 安装下载 4.1CentOS Docker 安装 4.2 Docker的基本组成 ?(面试)…...
HTTP Get 和 Post 的区别
分析&回答 使用规范 根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。 根据HTTP规范,POST表示可能修改变服务器上的资源的请求。 传递参数 GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中)。…...
C++超级迷宫游戏
游戏效果 用钥匙、护盾等道具帮助你的小人通过大门、墙、怪物、岩浆等困难到达终点。 游戏代码 #include<bits/stdc.h> #include<conio.h> #include<windows.h> using namespace std; void Color(int a) {if(a0) SetConsoleTextAttribute(GetStdHandle(STD…...
CUDA小白 - NPP(3) 图像处理 Color and Sampling Conversion
cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus…...
Android硬件通信之 串口通信
一,串口介绍 1.1 串口简介 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口; 串行接口(SerialInterface)是指数据一位一位地顺序…...
高防服务器面对DDOS攻击的威胁有何必要性
高防服务器面对DDOS攻击的威胁有何必要性?分布式拒绝服务(DDoS)攻击是一种常见而危险的网络攻击形式,它可以使目标网络服务器过载,导致服务不可用。本文将深入探讨DDoS攻击的威胁,以及高防服务器在抵御这种…...
VBA中如何将if写到一行
在VBA中,可以使用以下两种方式来编写一行if语句: 使用三元运算符: Dim result As String result "Yes" If True Else "No"在这个例子中,如果条件为真,则result变量的值为"Yes"&#…...
性能测试,python 内存分析工具 -memray
Memray是一个由彭博社开发的、开源内存剖析器;开源一个多月,已经收获了超8.4k的star,是名副其实的明星项目。今天我们就给大家来推荐这款python内存分析神器。 Memray可以跟踪python代码、本机扩展模块和python解释器本身中内存分配…...
Jmeter(二十八):beanshell的使用
Beanshell 是一种轻量级的 Java 脚本,纯 Java 编写的,能够动态的执行标准 java 语法及一些扩展脚本语法,类似于 javaScript,在工作中可能用的多的就是: Beanshell 取样器:跟Http取样器并列Beanshell前置处理器:一般放在Http请求下,在请求前处理一些数据Beanshell后置处…...
数学建模:层次分析法
🔆 文章首发于我的个人博客:欢迎大佬们来逛逛 层次分析法 步骤描述 将问题条理化,层次化,构建出一个有层次的结构模型。层次分为三类:目标层,准则(指标)层,方案层。比…...
POI-TL制作word
本文相当于笔记,主要根据官方文档Poi-tl Documentation和poi-tl的使用(最全详解)_JavaSupeMan的博客-CSDN博客文章进行学习(上班够用) Data AllArgsConstructor NoArgsConstructor ToString EqualsAndHashCode public …...
大数据Flink(七十一):SQL的时间属性
文章目录 SQL的时间属性 一、Flink三种时间属性简介...
51单片机项目(7)——基于51单片机的温湿度测量仿真
本次做的设计,是利用DHT11传感器,测量环境的温度以及湿度,同时具备温度报警的功能:利用两个按键,设置温度阈值的加和减,当所测温度大于温度阈值的时候,蜂鸣器就会响起,进行报警提示。…...
按钮控件之1---QPushButton 标准按钮/普通按钮控件
1、父类QAbstractButton 2、QPushButton按钮,是Qt常用的控件之一,提供普通的按钮功能。 通过信号槽机制接收触发信号并执行对应动作。3、创建QPushButton 它有三个构造函数: // 空对象 QPushButton(QWidget *parent nullptr); // 指定QPus…...
Ae 效果:CC Light Rays
生成/CC Light Rays Generate/CC Light Rays CC Light Rays(CC 光线)可以创建从光源发出并能穿过图层内容的光线效果。常用于制作光线透过门窗或云层的场景,或者用于创建神奇或梦幻的氛围感。 本效果会被限制在源图层的大小范围之内。 ◆ ◆…...
MPI之通信模式(标准,缓存,同步,就绪)
MPI缓冲区 由MPI自行维护的一块内存区域,也可由用户(MPI_Bsend)自行维护;发送方 维护一块发送缓冲区; 接收方 维护一块接收缓冲区。 数据收发过程: 当发送端将数据拷贝到自身的数据缓冲区后(注意这里是拷贝,即数据到…...
面试官:说一下 MyBatis 的一级缓存和二级缓存 ?
目录 1. MyBatis 的缓存机制 2. 为什么不默认开启 MyBatis 的二级缓存 3. MyBatis 如何开启二级缓存 4. MyBatis 有哪些缓存清除策略 1. MyBatis 的缓存机制 MyBayis 中包含两级缓存:一级缓存和二级缓存 1. 一级缓存是 SqlSession 级别的,是 MyBati…...
【Spring Boot 3 + Vue 3】宠物医院智能诊疗管理系统 全功能展示 | 前后端分离实战
宠物医院智能诊疗管理系统 — Spring Boot 3 Vue 3 全栈实战 项目简介基于 Spring Boot 3 Vue 3 Bootstrap 5 MyBatis-Plus MySQL 构建的宠物医院智能诊疗管理系统,采用前后端分离架构,实现了从游客浏览、在线预约、诊疗记录到物资管理的完整业务闭…...
GeoServer零配置入门:如何用绿色版快速搭建本地地图服务器(含端口自定义技巧)
GeoServer零配置入门:如何用绿色版快速搭建本地地图服务器(含端口自定义技巧) 在GIS开发领域,快速搭建本地测试环境是每个开发者必备的技能。GeoServer作为开源地图服务器中的佼佼者,其绿色版更是提供了即解压即用的便…...
Leather Dress Collection 在软件测试中的应用:自动化生成测试用例与报告
Leather Dress Collection 在软件测试中的应用:自动化生成测试用例与报告 最近和几个做测试的朋友聊天,大家普遍吐槽一件事:写测试用例和整理测试报告,太费时间了。尤其是面对一个复杂的新功能,或者是一大堆历史遗留的…...
OpenClaw+SecGPT-14B:构建无需编程的内网资产管理系统
OpenClawSecGPT-14B:构建无需编程的内网资产管理系统 1. 为什么需要无代码内网资产管理 去年接手公司IT运维时,我发现内网设备清单还是三年前的Excel表格。每当新设备接入或旧设备淘汰,手动更新文档总会被遗忘。更麻烦的是,不同…...
从PX4的FRD到Mavros的FLU:手把手教你正确配置`setpoint_raw/local`话题发布无人机目标点
从PX4的FRD到Mavros的FLU:无人机坐标系转换实战指南 当你在ROS环境下通过Mavros向PX4飞控发送位置指令时,是否遇到过无人机朝完全相反方向飞行的情况?这种"方向错乱"的根源往往在于坐标系理解的偏差。本文将彻底解开PX4与Mavros之间…...
双模型协作!OpenClaw同时调用Qwen3-4B与Codex完成编程任务
双模型协作!OpenClaw同时调用Qwen3-4B与Codex完成编程任务 1. 为什么需要双模型协作 作为一个经常需要写代码的技术博主,我一直在寻找更高效的编程方式。传统的单模型调用虽然能完成基础任务,但在复杂场景下往往力不从心——要么生成的代码…...
SagerNet数据库架构完全指南:Room与DataStore在代理工具中的最佳实践
SagerNet数据库架构完全指南:Room与DataStore在代理工具中的最佳实践 SagerNet作为Android平台上的通用代理工具链,其强大的数据库架构设计是其核心竞争力的关键。通过深入分析SagerNet的Room数据库与DataStore的完美结合,我们可以了解现代A…...
MQ之KAFKA (broker 高可用)
Kafka KRaft 核心知识点(面试+生产极简版) KRaft(Kafka Raft):Kafka 2.8+ 引入、3.3+ 生产可用,完全替代 Zookeeper 的内置元数据一致性协议(基于 Raft)。 一句话背诵 内置 Raft、无 ZK、元数据自管理、选举更快、吞吐更高、架构极简。 1. 核心概念(必背) Control…...
Windows效率翻倍!这些隐藏的Win+R命令和CMD技巧你用过几个?
Windows效率革命:解锁WinR与CMD的终极生产力指南 你是否曾在同事飞速敲击键盘时暗自惊叹?那些看似简单的组合键背后,藏着Windows系统最强大的效率武器库。今天我们要探索的不仅是快捷键列表,而是一套完整的生产力操作系统——从Wi…...
基于Python的电影订票系统毕业设计源码
博主介绍:✌ 专注于Java,python,✌关注✌私信我✌具体的问题,我会尽力帮助你。一、研究目的本研究旨在设计并实现一个基于Python的电影订票系统,以满足现代观众对于便捷、高效电影购票服务的需求。具体研究目的如下: 首先…...
