【深入浅出设计模式--状态模式】

深入浅出设计模式--状态模式

  • 一、背景
  • 二、问题
  • 三、解决方案
  • 四、 适用场景总结
  • 五、后记

一、背景

状态模式是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。其与有限状态机的概念紧密相关,如下所示:
在这里插入图片描述

二、问题

在实际设计编码UI界面的工作中,有很多人应该都遇到过类似这样的场景:当鼠标移动或者点击某个标签、按钮等组件时,对应组件上会根据鼠标的状态进行不同的响应,比如颜色大小的变化。如果状态有很多种,那我们就会在代码中添加许多条件判断(if-else、switch),有时候可能一条语句中的条件多达十来个,出现bug的时候调试起来相当恶心。基于这个问题,下面使用状态模式逐步解决。

三、解决方案

  1. 首先在上下文类Context中定义改变状态的接口changeState,并聚合了指向当前状态的IState对象指针,changeState的参数即为new生成的具体状态类NormorlState等,调用paintTags函数时会调用当前状态类的doPaint函数进行该状态下的绘制操作。
  2. 接口状态类IState中提供了doPaint纯虚函数,每个具体状态类会继承并重写doPaint,在doPaint中可以调用setHoverState等函数对Context类对象的成员变量进行修改,同步状态与操作。
  3. 为了对每个状态类对象进行复用,采用单例模式提供GetInstance函数供Context调用。
    类图如下:
    在这里插入图片描述
  4. 上面的类结构中,因为每个具体状态类都是单例模式,提供除了名字不同之外相同的代码块,因此会有许多重复代码,因此想到在接口状态类IStateBase和具体状态类之间插入一个单例模板类IStateTemplate专门提供静态GetInstance函数,然后每个具体状态类对其继承和模板特化,这样在具体状态类中只需要实现doPaint函数即可。
  5. 各类达到高度凝练与抽象,每一层只专注某一功能的效果。后续如果有新加入一种状态,只需要特化IStateTemplate,然后重写doPaint函数即可,其他状态的代码无需修改,减少大量条件判断的同时也降低了出错的概率。
    改进后的类图如下:
    在这里插入图片描述
  6. 该模式下各类之间交互的时序图如下:
    在这里插入图片描述
  7. Context类关键代码截图:
    在这里插入图片描述
  8. State相关类关键代码截图:
    在这里插入图片描述

四、 适用场景总结

  • 如果对象需要根据自身当前状态(成员变量值)进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可使用状态模式。
  • 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。
  • 如果状态机只有很少的几个状态,或者很少发生改变,那么应用该模式可能会显得小题大作。

五、后记

以上所有内容均为原创,代码已上传至gayhub:
https://github.com/gangster-puppy/Design-Pattern.git

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

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

相关文章

解决Three.js辉光背景不透明

使用此pass canvas元素的background都能看到 不过相应的辉光颜色和背景颜色不相容的地方看起来颜色会怪一些 如图 不过如果是纯色就没什么问题了 //ts-nocheck /** Author: hongbin* Date: 2023-04-06 11:44:14* LastEditors: hongbin* LastEditTime: 2023-04-06 11:49:23* De…

电缆工厂 3D 可视化管控系统 | 智慧工厂

近年来,我国各类器材制造业已经开始向数字化生产转型,使得生产流程变得更加精准高效。通过应用智能设备、物联网和大数据分析等技术,企业可以更好地监控生产线上的运行和质量情况,及时发现和解决问题,从而提高生产效率…

libevent源码学习3---事件event

libevent源码学习3—事件event libevent 的基本操作单元是事件。每个事件代表一组条件的集合, 这些条件包括: 文件描述符已经就绪, 可以读取或者写入文件描述符变为就绪状态,可以读取或者写入(仅对于边沿触发 IO)超时事件发生某信号用户触发事件 所有事件具有相似的生命周期。…

SpringBoot集成Redis、Redisson保姆教程【附源码】

1. SpringBoot集成Redis 关于Redis的安装,这里就不重复介绍了,需要的朋友可以看我之前的博文Redis多系统安装(Windows、Linux、Ubuntu) Redis原生命令大全,作者整理的很详细,大部分命令转化为java命令基本也是关键词 Redis 命令参考 接下来开始我们的正题,一起学习下…

Windows域环境下,GPO部署的注意事项。

文章目录 GPO部署的注意事项1. 计划和测试2. 命名和文档化3. 安全性4. OU(组织单位)结构5. GPO优先级6. 禁用不需要的GPO7. 回滚计划8. 日志和审计9. 版本控制10. 性能影响11. 考虑用户体验12. 更新和维护 推荐阅读 在Windows域环境中,使用组…

深度学习推荐系统(二)Deep Crossing及其在Criteo数据集上的应用

深度学习推荐系统(二)Deep Crossing及其在Criteo数据集上的应用 在2016年, 随着微软的Deep Crossing, 谷歌的Wide&Deep以及FNN、PNN等一大批优秀的深度学习模型被提出, 推荐系统全面进入了深度学习时代, 时至今日&#xff0c…

跨站请求伪造(CSRF)

文章目录 渗透测试漏洞原理跨站请求伪造(CSRF)1. CSRF概述1.1 基本概念1.1.1 关键点1.1.2 目标 1.2 CSRF场景1.2.1 银行账户转账1.2.2 构造虚假网站1.2.3 场景建模1.2.4 实验 1.3 CSRF类别1.3.1 POST方式 1.4 CSRF验证1.4.1 CSRF Poc generator 1.5 XSS与…

SpringAOP详解(下)

proxyFactory代理对象创建方式和代理对象调用方法过程: springaop创建动态代理对象和代理对象调用方法过程: 一、TargetSource的使用 Lazy注解,当加在属性上时,会产生一个代理对象赋值给这个属性,产生代理对象的代码为…

政府科技项目验收全流程分享

科技验收测试 (验收申请→主管部门初审→科技厅审核→组织验收→归档备案→信用管理): (一)验收申请 项目承担单位通过省科技业务管理系统提交验收申请。 按期完成的项目,项目承担单位应当在项目合同书…

C 实现Window/DOS 键盘监听事件

今天是重新复习C语言实现的第一天,今天想编写C 对Windwos/Dos 键盘事件的学习。但是我在安装Visual Studio 2022 没有安装MFC 框架,今天记录下VS追加 MFC框架。 Visual Studio 2022 追加MFC 1、打开vs,点击创建新项目,右侧滑动框…

docker 学习-- 04 实践2 (lnpmr环境)

docker 学习 系列文章目录 docker 学习-- 01 基础知识 docker 学习-- 02 常用命令 docker 学习-- 03 环境安装 docker 学习-- 04 实践 1(宝塔) docker 学习-- 04 实践 2 (lnpmr环境) 文章目录 docker 学习 系列文章目录1. 配…

5G智能网关如何解决城市停车痛点难点

2023年上半年,我国汽车新注册登记1175万辆,同比增长5.8%,88个城市汽车保有量超过100万辆,北京、成都等24个城市超过300万辆。随着车辆保有量持续增加,停车难问题长期困扰城市居民,也导致城市路段违停普遍、…

制作鲜花商城小程序的详细步骤

如果你是一个新手商家,想要进入鲜花团购市场,但是不知道如何制作一个小程序商城,那么这篇文章就是为你准备的。以下是制作鲜花团购小程序商城的详细步骤: 1. 登录乔拓云平台后台,进入商城管理页面 首先,你需…

【openGauss2.1.0 TPC-C数据导入】

openGauss2.1.0 TPC-C数据导入 一、下载tpch测试数据二、导入测试数据 一、下载tpch测试数据 使用普通用户如omm登录服务器执行如下命令下载测试数据库:git clone https://gitee.com/xzp-blog/tpch-kit.git二、导入测试数据 进入dbgen目录下,生成makef…

stm32+FreeRTOS遇到的坑

问题 最近把项目移植进FreeRTOS时,发现开始任务都不能启动; 机器是stm32f407,使用的arm固件和FreeRTOS都是最新版本; 裸机运行没有问题,但是使用任务运行就运行不了; 排查 首先尝试了教程用的点灯代码…

虚拟化技术:云计算发展的核心驱动力

文章目录 虚拟化技术的概念和作用虚拟化技术的优势虚拟化技术对未来发展的影响结论 🎉欢迎来到AIGC人工智能专栏~虚拟化技术:云计算发展的核心驱动力 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系…

WebGL矩阵变换库

目录 矩阵变换库: Matrix4对象所支持的方法和属性如表所示: 方法属性规范: 虽然平移、旋转、缩放等变换操作都可以用一个44的矩阵表示,但是在写WebGL程序的时候,手动计算每个矩阵很耗费时间。为了简化编程&#xf…

opencv 案例05-基于二值图像分析(简单缺陷检测)

缺陷检测,分为两个部分,一个部分是提取指定的轮廓,第二个部分通过对比实现划痕检测与缺角检测。本次主要搞定第一部分,学会观察图像与提取图像ROI对象轮廓外接矩形与轮廓。 下面是基于二值图像分析的大致流程 读取图像将图像转换…

SQLite 3.43.0 发布,又有啥新功能?

SQLite 开发团队于 2023 年 08 月 24 日发布了 SQLite 3.43.0 版本。本文给大家分析一下该版本的更新。 全文索引 SQLite 3.43.0 增加了 Contentless-Delete FTS5 索引。这是一种 FTS5 全文索引的变种,不存储被索引的内容,同时支持数据的删除操作。 例…

Rust多线程编程

Rust多线程编程 文章目录 Rust多线程编程使用线程模块创建线程线程传参闭包(匿名函数)值捕获不可变引用捕获可变引用捕获 线程闭包传参更优雅地传参 回收线程线程同步和通信channel 通道mutex 互斥锁Barrier 栅栏Atomic Types 原子类型 使用线程模块 ru…