设计模式-状态(State)模式
目录
开发过程中的一些场景
状态模式的简单介绍
状态模式UML类图
类图讲解
适用场景
Java中的例子
案例讲解
什么是状态机
如何实现状态机
SpringBoot状态自动机
优点
缺点
与其他模式的区别
小结
-
开发过程中的一些场景
- 我们在平时的开发过程中,经常会遇到这样一种情况:就是需要我们处理一个对象的不同状态下的不同行为
- 比如最常见的就是订单,订单有很多种状态,每种状态又对应着不同的操作,有些操作是相同的,有些操作是不同的
- 再比如一个音乐播放器程序,在播放器缓冲音乐,播放,暂停,快进,快退,终止等的情况下又对应着各种操作
- 有些操作在某些情况下是允许的,有些操作是不允许的
- 还有很多不同的场景,这里就不一一列举了
-
状态模式的简单介绍
- 状态模式是行为型设计模式的一种,状态模式允许对象改变它的行为
- 其设计理念是当对象的内部状态发生改变时,随之改变其行为
- 状态和行为之间是一一对应的
- 该模式主要用于,对象的行为依赖于它的状态,并且其行为是随着状态的改变而切换时
- 这种模式接近于有限状态机的概念
- 状态模式可以被理解为策略模式,它能够通过调用在模式接口中定义的方法来切换策略
-
状态模式UML类图
-
类图讲解
- State:抽象状态接口(也可以定义成抽象类),该接口封装了所有状态所对应的行为
- ConcreteStateA/B:具体状态类,该类实现了抽象状态接口,会根据自身对应的状态来实现接口中定义的方法,还有另一个功能是指明如何过渡到下一个状态
- Context:环境(上下文)角色,该类负责状态的切换,还持有一个State实例,代表当前环境所处状态
-
适用场景
- 在以下两种情况下,请使用State模式:
- 对象的行为取决于它的状态,并且它必须在运行时根据状态更改其行为
- 根据对象状态的不同,操作有大量的条件语句;此状态通常由一个或多个枚举常量表示;通常,几个操作将包含此相同的条件结构;状态模式把条件语句的分支分别放入单独的类中;这样一来,你就可以将对象的状态视为独立的对象,该对象可以独立于其他对象而变化
- 在以下两种情况下,请使用State模式:
-
Java中的例子
- javax.faces.lifecycle.Lifecycle#execute() 方法由 FacesServlet 控制,其行为取决于当前生命周期阶段
-
案例讲解
- 场景:
- 大家的热情直接影响up的更新频率,那么此时事件和状态就出现了:
- 事件:投币,点赞,收藏
- 状态:SOMETIME(想起来什么时候更新就什么时候更新),OFTEN(会经常更新下),USUALLY(有事也更新),ALWAYS(没停过的肝)
- 我们可以得到一个关系:
- 投币:UpSometimeState -> UpOftenState
- 点赞:UpOftenState -> UpUsuallyState
- 收藏:UpUsuallyState -> UpAlwaysState
- 英文频率从低到高:Sometime -> Often -> Usually -> Always
- 大家的热情直接影响up的更新频率,那么此时事件和状态就出现了:
- 代码:
- 我们先定义一个状态的抽象类,用来表示up的更新频率
- 接着我们定义子类,分别表示每个不同的状态:
- 我们还需要一个上下文环境来进行状态的流转关联
- 接着我们写一个客户端来模拟调用流程:
- 此时,状态模式便完成了,可以看到我们没有用到if else,便完成了判断
- 每个状态也是由一个类来代替的,我们对其中一个状态进行的改动,不会影响其他的状态逻辑
- 通过这样的方式,很好的实现了对扩展开放,对修改关闭的原则
- 我们看下输出:
- 场景:
-
什么是状态机
- 定义:
- 有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件
- 要素:
- 现态:是指当前所处的状态
- 条件:又称为“事件”;当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移
- 动作:条件满足后执行的动作;动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态;动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态
- 次态:条件满足后要迁往的新状态;“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了
- 定义:
-
如何实现状态机
- 实现状态机主要体现在两部分:
- 画出状态转换图和将有限状态机用代码实现
- 其中代码实现部分其实就是状态模式的实现
- 画出状态转换图
- 找出所有状态(圆圈表示)
- 找出所有状态间的转换条件(圆圈间的线段表示)
- 分析每个状态需要执行的策略(圆圈边的大括号表示)
- 将有限状态机用代码实现
- 定义一个状态机类
- 根据状态转换图的状态节点(圆圈)**,定义状态**(可使用类(推荐),枚举或无符号整数)
- 根据状态转换图的转换条件(边)**,实现转换动作**方法
- 实现状态机主要体现在两部分:
-
SpringBoot状态自动机
- 完全能结合spring强大的IOC和AOP,实现一个状态自动机
- 还是刚刚的场景,我们通过Spring StateMachine来实现下
- 代码
- 包的引入:
- 定义状态和事件枚举
- 创建状态机配置类
- 注解监听器
- 创建应用Controller来完成流程
- 说明
- 我们可以对如何使用Spring StateMachine做如下小结:
- 定义状态和事件枚举
- 为状态机定义使用的所有状态以及初始状态
- 为状态机定义状态的迁移动作
- 为状态机指定监听处理器
-
优点
- 结构清晰:
- 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”
- 将状态转换显示化,减少对象间的相互依赖:
- 将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖
- 状态类职责明确,有利于程序的扩展:
- 通过定义新的子类很容易地增加新的状态和转换
- 结构清晰:
-
缺点
- 状态模式的使用必然会增加系统的类与对象的个数
- 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱
- 状态模式对开闭原则的支持并不太好:
- 对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码
-
与其他模式的区别
- 状态模式与策略模式看起来像双胞胎,但他们还是不相同的
-
小结
- 状态模式的核心是封装,将状态以及状态转换逻辑封装到类的内部来实现,也很好的体现了“开闭原则”和“单一职责原则”
- 每一个状态都是一个子类,不管是修改还是增加状态,只需要修改或者增加一个子类即可
- 在我们的应用场景中,状态数量以及状态转换远比上述例子复杂,通过“状态模式”避免了大量的if-else代码,让我们的逻辑变得更加清晰
- 同时由于状态模式的良好的封装性以及遵循的设计原则,让我们在复杂的业务场景中,能够游刃有余地管理各个状态
相关文章:
设计模式-状态(State)模式
目录 开发过程中的一些场景 状态模式的简单介绍 状态模式UML类图 类图讲解 适用场景 Java中的例子 案例讲解 什么是状态机 如何实现状态机 SpringBoot状态自动机 优点 缺点 与其他模式的区别 小结 开发过程中的一些场景 我们在平时的开发过程中,经常会…...
oracle怎么存放json好
Oracle数据库提供了多种方式来存储JSON数据。你可以将JSON数据存储在VARCHAR2、CLOB或BLOB数据类型中,或者使用Oracle提供的JSON数据类型。 如果你选择使用VARCHAR2数据类型来存储JSON数据,你可以直接将JSON字符串存储在其中。例如: CREATE…...
【计算机网络】—— 详解码元,传输速率的计算|网络奇缘系列|计算机网络
🌈个人主页: Aileen_0v0🔥系列专栏: 一见倾心,再见倾城 --- 计算机网络~💫个人格言:"没有罗马,那就自己创造罗马~" 目录 码元 速率和波特 思考1 思考2 思考3 带宽(Bandwidth) 📝总结 码元…...
[ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
文章目录 一、前言二、在 Azure Portal 中创建 VM三、验证已创建的虚拟机资源3.1 方法一:在虚拟机服务中查看验证3.1 方法二:在资源组服务中查看验证 四、文末总结 一、前言 本文会开始创建新系列的专栏,专门更新 Azure 云实践相关的文章。 …...
计算机网络:网络层(无分类编址CIDR、计算题讲解)
带你快速通关期末 文章目录 前言一、无分类编址CIDR简介二、构成超网三、最长前缀匹配总结 前言 我们在前面知道了分类地址,但是分类地址又有很多缺陷: B类地址很快将分配完毕!路由表中的项目急剧增长! 一、无分类编址CIDR简介 无分类域间路由选择CI…...
Learning Semantic-Aware Knowledge Guidance forLow-Light Image Enhancement
微光图像增强(LLIE)研究如何提高照明并生成正常光图像。现有的大多数方法都是通过全局和统一的方式来改善低光图像,而不考虑不同区域的语义信息。如果没有语义先验,网络可能很容易偏离区域的原始颜色。为了解决这个问题࿰…...
关于嵌入式开发的一些信息汇总:开发模型以及自托管开发(二)
关于嵌入式开发的一些信息汇总:开发模型及自托管开发(二) 2 自托管开发2.2 构建 Raspberry Pi 内核2.3 安装内核2.4 总结 3 连接目标板3.1 Raspberry Pi 上的网络设置3.2 Ssh、rsh、rlogin 和 telnet 连接到目标 4 应用程序开发4.1 在目标板上…...
【JavaEE】多线程案例 - 定时器
作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&…...
网络小测------
使用软件PT7.0按照上面的拓扑结构建立网络,进行合理配置,使得所有计算机之间能够互相通信。并且修改各交换机的系统名称为:学号_编号,如你的学号为123,交换机Switch0的编号为0,则系统名称为123_0࿱…...
基于linux系统的Tomcat+Mysql+Jdk环境搭建(二)jdk1.8 linux 上传到MobaXterm 工具的已有session里
【JDK安装】 1.首先下载一个JDK版本 官网地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载1.8版本,用红框标注出来了: 也许有的同学看到没有1.8版本,你可以随便下载一个linux的…...
04-Nacos中负载均衡规则的配置
负载均衡规则 同集群优先 默认的ZoneAvoidanceRule实现并不能根据同集群优先的规则来实现负载均衡,Nacos中提供了一个实现叫NacosRule可以优先从同集群中挑选服务实例 当服务消费者在本地集群找不到服务提供者时也会去其他集群中寻找,但此时会在服务消费者的控制台报警告 第…...
Kotlin 中的 `use` 关键字:优化资源管理(避免忘记inputStream.close() ?)
在 Android开发中,正确且高效地管理资源是至关重要的。use 关键字在 Kotlin 中为资源管理提供了一个简洁且强大的解决方案。它主要用于自动管理那些需要关闭的资源,比如文件、网络连接等。 一、use 关键字的工作原理 🤖 use 是一个扩展函数…...
时序预测 | Python实现GRU-XGBoost组合模型电力需求预测
时序预测 | Python实现GRU-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现GRU-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…...
扁平化菜单功能制作
网页效果: HTML部分: <body><ul class"nav"><li><a href"javascript:void(0);">菜单项目一</a><ul><li>子菜单项01</li><li>子菜单项02</li><li>子菜单项03<…...
网络基础——路由协议及ensp操作
目录 一、路由器及路由表 1.路由协议: 2.路由器转发原理: 3.路由表: 二、静态路由优缺点及特殊静态路由默认路由 1.静态路由的优缺点: 2.下一跳地址 3.默认路由 三、静态路由配置 四、补充备胎 平均负载 五、补充&…...
Python-折线图可视化
折线图可视化 1.JSON数据格式2.pyecharts模块介绍3.pyecharts快速入门4.创建折线图 1.JSON数据格式 1.1什么是JSON JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符串 1.2主要功能json就是一种在各个编程语言中流…...
C++类与对象 (上)
目录 前言: 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言: C语言是面向过程的,关注的是过…...
no module named ‘xxx‘
目录结构如下 我想在GCNmodel的model里引入layers的GraphConvolution:from GCNmodel.layers import GraphConvolution,但这样却报错no module named GCNmodel,而且用from layers import GraphConvolution也不行。然后用sys.path.appen(xxx)…...
Go实现MapReduce
背景 当谈到处理大规模数据集时,MapReduce是一种备受欢迎的编程模型。它最初由Google开发,用于并行处理大规模数据以提取有价值的信息。MapReduce模型将大规模数据集分解成小块,然后对这些小块进行映射和归约操作,最终产生有用的…...
Axure的交互样式和情形
Axure的交互样式和情形 交互样式 Axure是一个流行的原型设计工具,它允许您创建交互式原型,模拟应用程序或网站的功能和用户界面。在Axure中,您可以设置各种交互样式来使原型更加生动和真实。 链接触发器:通过给一个元素添加链接…...
Mybatis在新增某个数据后,如何获取新增数据的id
在某些业务中,我们在新增一条数据之后,需要拿到这条数据的id来对这条数据进行后续的一个操作,如何拿取id呢? 使用的是<insert> 中的useGeneratedKeys 和 keyProperty 两个属性 1.在Mybatis Mapper文件中添加属性 “useGene…...
12.4~12.14概率论复习与相应理解(学习、复习、备考概率论,这一篇就够了)
未分配的题目 概率计算(一些转换公式与全概率公式)与实际概率 ,贝叶斯 一些转换公式 相关性质计算 常规,公式的COV与P 复习相关公式 计算出新表达式的均值,方差,再套正态分布的公式 COV的运算性质 如…...
关于多重背包的笔记
多重背包可以看作01背包的拓展, 01背包是选或者不选。多重背包是选0个一直到选s个。 for (int i 1; i < n; i) {for (int j m; j > w[i]; --j){f[j] max(f[j], f[j - 1*w[i]] 1*v[i], f[j - 2*w[i]] 2*v[i],...f[j - s*w[i]] s*v[i]);} } 由上述伪代码…...
如何使用 Java 的反射
如何使用 Java 的反射? 通过一个全限类名创建一个对象 Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver 类已经被加载到 jvm 中,并且完成了类的初始化工作就行了 类名.class; 获取 Class<?> clz 对象对…...
PLC-Recorder V3 修改服务器和客户端通讯端口的方法
PLC-Recorder V3是服务器和客户端的架构,他们之间用TCP通讯。如果客户端无法与服务器建立连接(重启也无效,并且确保没有老版本的PLC-Recorder在运行),则可能是端口被占用了。这时候需要修改他们之间的通讯端口…...
libevent服务GET/POST的简单使用
目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信,比较常用的使用POST和GET方式…...
MySQL 系列:注意 ORDER 和 LIMIT 联合使用的陷阱
文章目录 前言背后的原因ORDER BY 排序列存在相同值时返回顺序是不固定的LIMIT 和 ORDER BY 联合使用时的行为ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引 如何解决其它说明个人简介 前言 不知道大家在在分页查询中有没有遇到过这个问题,分页查…...
通过实例理解OAuth2授权
在之前的《通过实例理解Go Web身份认证的几种方式[1]》和《通过实例理解Web应用授权的几种方式[2]》两篇文章中,我们对Web应用身份认证(AuthN)和授权(AuthZ)的几种方式做了介绍并配以实例增强理解。 在现实世界中,还有一大类的认证与授权是在前面的文章中…...
MATLAB2022安装下载教程
安装包需从夸克网盘自取: 链接:https://pan.quark.cn/s/373ffc9213a1 提取码:N7PW 1.将安装包解压 2.以管理员的身份运行文件夹中的setup文件 3.点击高级选项--->我有文件安装密钥 4. 选择【是】,进入下一步 5.输入密钥 0532…...
从零开始搭建Go语言开发环境
https://www.liwenzhou.com/posts/Go/install_go_dev/ “go 命令现在默认在模块感知模式下构建包,即使没有 go.mod 存在也是如此。 “您可以将 GO111MODULE 设置为 auto,仅当当前目录或任何父目录中存在 go.mod 文件时,才能启用模块感知模式…...
做设计那个素材网站最好/企业seo关键字优化
1,git安装完之后,打开git bash 命令行,执行以下命令: ssh-keygen -t rsa 然后按三下默认回车 2.执行查看公钥的命令: cat ~/.ssh/id_rsa.pub 3.最后把公钥复制放在阿里云的增加公钥里面 在本地仓库执行初始化&am…...
现在流行的网站开发语言/网站查询进入
Spring Cloud Gateway除了具备请求路由功能之外,也支持对请求的过滤。通过Zuul网关类似,也是通过过滤器的形式来实现的。那么接下来我们一起来研究一下Gateway中的过滤器3.3.1 过滤器基础(1) 过滤器的生命周期Spring Cloud Gatewa…...
贵阳好的网站建设公司/网站如何做优化推广
【木头Cocos2d-x】Lua篇(第03章):简单解析Lua的堆栈 上一章传送门:http://blog.csdn.net/musicvs/article/details/8440919 经过上一章的讲解,相信大家也看到了,Lua的堆栈是很重要不可或缺的,就…...
自己做的网站怎么爬数据/搜索引擎推广的常见形式有
说起独立博客的技术演变,从数据库到纯文本放git是一大进步,从HTML到markdown又是一大进步。 解析技术有没有进步呢?既然markdown是纯文本了,再用PHP/Python/Ruby去实时解析,多么多此一举啊(比如github用的J…...
义乌小商品批发网上进货/windows优化大师怎么样
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid3886 题意:给一定区间[A,B],一串由/,\,-组成的符号串。求满足符号串的数字个数。 •/表示数字从左到右递增•\表示数字从左到右递减•-表示数字从左到右相等分析:dp[i][j][k]…...
Add-ons wordpress/google play官网下载
1. 什么是ORM? 对象-关系映射(Object-Relational Mapping,简称ORM),面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业…...