当前位置: 首页 > news >正文

设计模式-状态(State)模式

目录

开发过程中的一些场景

状态模式的简单介绍

状态模式UML类图

类图讲解

适用场景

Java中的例子

案例讲解

什么是状态机

如何实现状态机

SpringBoot状态自动机

优点

缺点

与其他模式的区别

小结


  • 开发过程中的一些场景

    • 我们在平时的开发过程中,经常会遇到这样一种情况:就是需要我们处理一个对象的不同状态下的不同行为
    • 比如最常见的就是订单,订单有很多种状态,每种状态又对应着不同的操作,有些操作是相同的,有些操作是不同的
    • 再比如一个音乐播放器程序,在播放器缓冲音乐,播放,暂停,快进,快退,终止等的情况下又对应着各种操作
    • 有些操作在某些情况下是允许的,有些操作是不允许的
    • 还有很多不同的场景,这里就不一一列举了
  • 状态模式的简单介绍

    • 状态模式是行为型设计模式的一种,状态模式允许对象改变它的行为
    • 其设计理念是当对象的内部状态发生改变时,随之改变其行为
    • 状态和行为之间是一一对应的
    • 该模式主要用于,对象的行为依赖于它的状态,并且其行为是随着状态的改变而切换时
    • 这种模式接近于有限状态机的概念
    • 状态模式可以被理解为策略模式,它能够通过调用在模式接口中定义的方法来切换策略
  • 状态模式UML类图

  • 类图讲解

    • State:抽象状态接口(也可以定义成抽象类),该接口封装了所有状态所对应的行为
    • ConcreteStateA/B:具体状态类,该类实现了抽象状态接口,会根据自身对应的状态来实现接口中定义的方法,还有另一个功能是指明如何过渡到下一个状态
    • Context:环境(上下文)角色,该类负责状态的切换,还持有一个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的更新频率

      • 接着我们定义子类,分别表示每个不同的状态:

      • 我们还需要一个上下文环境来进行状态的流转关联

      • 接着我们写一个客户端来模拟调用流程:

    • 此时,状态模式便完成了,可以看到我们没有用到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)研究如何提高照明并生成正常光图像。现有的大多数方法都是通过全局和统一的方式来改善低光图像,而不考虑不同区域的语义信息。如果没有语义先验,网络可能很容易偏离区域的原始颜色。为了解决这个问题&#xff0…...

关于嵌入式开发的一些信息汇总:开发模型以及自托管开发(二)

关于嵌入式开发的一些信息汇总:开发模型及自托管开发(二) 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&#xff1…...

基于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 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…...

扁平化菜单功能制作

网页效果&#xff1a; HTML部分&#xff1a; <body><ul class"nav"><li><a href"javascript:void(0);">菜单项目一</a><ul><li>子菜单项01</li><li>子菜单项02</li><li>子菜单项03<…...

网络基础——路由协议及ensp操作

目录 一、路由器及路由表 1.路由协议&#xff1a; 2.路由器转发原理&#xff1a; 3.路由表&#xff1a; 二、静态路由优缺点及特殊静态路由默认路由 1.静态路由的优缺点&#xff1a; 2.下一跳地址 3.默认路由 三、静态路由配置 四、补充备胎 平均负载 五、补充&…...

Python-折线图可视化

折线图可视化 1.JSON数据格式2.pyecharts模块介绍3.pyecharts快速入门4.创建折线图 1.JSON数据格式 1.1什么是JSON JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符串 1.2主要功能json就是一种在各个编程语言中流…...

C++类与对象 (上)

目录 前言&#xff1a; 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言&#xff1a; C语言是面向过程的&#xff0c;关注的是过…...

no module named ‘xxx‘

目录结构如下 我想在GCNmodel的model里引入layers的GraphConvolution&#xff1a;from GCNmodel.layers import GraphConvolution&#xff0c;但这样却报错no module named GCNmodel&#xff0c;而且用from layers import GraphConvolution也不行。然后用sys.path.appen(xxx)…...

Go实现MapReduce

背景 当谈到处理大规模数据集时&#xff0c;MapReduce是一种备受欢迎的编程模型。它最初由Google开发&#xff0c;用于并行处理大规模数据以提取有价值的信息。MapReduce模型将大规模数据集分解成小块&#xff0c;然后对这些小块进行映射和归约操作&#xff0c;最终产生有用的…...

Axure的交互样式和情形

Axure的交互样式和情形 交互样式 Axure是一个流行的原型设计工具&#xff0c;它允许您创建交互式原型&#xff0c;模拟应用程序或网站的功能和用户界面。在Axure中&#xff0c;您可以设置各种交互样式来使原型更加生动和真实。 链接触发器&#xff1a;通过给一个元素添加链接…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序&#xff0c;无论是测试应用程序、搜寻漏洞还是收集情报&#xff0c;它们都能提升工作流程。 FoxyProxy 代理管理工具&#xff0c;此扩展简化了使用代理&#xff08;如 Burp…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...

Android Framework预装traceroute执行文件到system/bin下

文章目录 Android SDK中寻找traceroute代码内置traceroute到SDK中traceroute参数说明-I 参数&#xff08;使用 ICMP Echo 请求&#xff09;-T 参数&#xff08;使用 TCP SYN 包&#xff09; 相关文章 Android SDK中寻找traceroute代码 设备使用的是Android 11&#xff0c;在/s…...

【Zephyr 系列 16】构建 BLE + LoRa 协同通信系统:网关转发与混合调度实战

🧠关键词:Zephyr、BLE、LoRa、混合通信、事件驱动、网关中继、低功耗调度 📌面向读者:希望将 BLE 和 LoRa 结合应用于资产追踪、环境监测、远程数据采集等场景的开发者 📊篇幅预计:5300+ 字 🧭 背景与需求 在许多 IoT 项目中,单一通信方式往往难以兼顾近场数据采集…...