设计模式-状态(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代码,让我们的逻辑变得更加清晰
    • 同时由于状态模式的良好的封装性以及遵循的设计原则,让我们在复杂的业务场景中,能够游刃有余地管理各个状态

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

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

相关文章

【Android】在Android上使用mlKit构建人脸检测程序

在Android上构建人脸检测程序 目录 1、导入mlKit依赖包2、配置人脸检测器并且获取人脸检测器3、加载图片资源4、调用人脸检测器5、绘制矩形边框6、完整代码7、效果展示 1、导入mlKit依赖包 dependencies {// ...// Use this dependency to bundle the model with your appi…

CSS盒子的浮动与网页布局(重点,有电影页面案例)

浮动适用于那种盒子的并列布局 CSS 提供了三种传统布局方式(简单说,就是盒子如何进行排列顺序):  普通流(标准流)  浮动  定位 标准流(普通流/文档流) 所谓的标准流: 就是标签按照规定好默认方式排列. 1. 块级…

abap 如何debug 更新进程

今天在测试环境做一个外向交货单过账的时候,每次都会dump ST22中看到报错如下:DBSQL_DUPLICATE_KEY_ERROR 接着我就去SM13去看下在哪个跟新里面失败了 双击错误条目可以看到 那么我就想说去debug看看当时的变量到底是啥,为啥会主键重复&…

数据库的三大范式

第一范式: 属性不可分割:每个属性都是不可分割的原子项(实体的属性就是表中的列) 在上表中contact应该分为phone和adress两列 第二范式: 在满足第一范式的情况下,表中不存在部分依赖,非主键列…

压缩包文件暴力破解 -Server2005(解析)

任务五十一: 压缩包文件暴力破解 任务环境说明:Server2005 1. 通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机服务版本信息,将 Telnet 版本信息字符串 作为 Flag 提交; flag:Microsoft Windows XP telnetd 2. 通过本地PC中渗透测试平台Kali对服务器场景Windows进行渗透测…

云演CTF Blog

1、啥也搞不了,扫目录。出来个console 2、有显示锁掉了 3、抓包,改返回包 改成true,放包 不好意思,不会了,哈哈哈哈哈哈哈哈哈 你会的话,请告诉我,大佬

C++:命名空间

从今天正式开始对C的学习&#xff0c;这里只学习C对C的拓展&#xff0c;和C相同的部分在C语言专栏中都可以找到&#xff0c;我们先看一段C代码 #include<iostream> using namespace std; int main() {cout<<"hello world<<endl;return 0; } 同样也是打…

数学公式推导中 “:=“和“:=“的区别

A:B 将A定义为&#xff08;记为&#xff0c;令为&#xff09;B A:B 将B定义为&#xff08;记为&#xff0c;令为&#xff09;A

YOLOv8-Seg改进:轻量化卷积设计 | DualConv双卷积魔改v8结构

🚀🚀🚀本文改进: DualConv双卷积魔改v8结构,达到轻量化的同时并能够实现小幅涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升分割性能…

​【EI会议征稿中】#先投稿,先送审#第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)​

#先投稿&#xff0c;先送审# 第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 2024年3月1日-3日 | 中国南京 会议官网&#xff1a…

漏刻有时数据可视化Echarts组件开发(45)机场流程导航线和指示点的开发记录

路径线 ECharts中的路径线是指用于连接起点和终点的线。在ECharts中&#xff0c;路径图主要用于带有起点和终点信息的线数据的绘制&#xff0c;如地图上的航班、路线等。路径线可以用于展示数据点之间的连接关系&#xff0c;以及数据点之间的相对位置。 {//路径图name: 路线图…

Mr. Cappuccino的第65杯咖啡——MacOS安装Docker

MacOS安装Docker 下载Docker安装Docker查看Docker相关信息镜像加速 下载Docker Docker官网 Docker文档中心 Docker桌面版下载地址 安装Docker 查看Docker相关信息 docker --versiondocker info镜像加速 阿里云镜像加速器 "registry-mirrors": ["https://gq8…

SpringBoot 源码解析2:启动流程1

SpringBoot 源码解析2&#xff1a;启动流程1 1.启动方式2.SpringBootApplication3.SpringApplication3.1 构造器SpringApplication3.2 SpringApplication#run 3.3 SpringApplication#run 中关键方法3.1 SpringApplication#prepareEnvironment3.2 SpringApplication#prepareCont…

BIM 技术:角色漫游

本心、输入输出、结果 文章目录 BIM 技术&#xff1a;角色漫游前言BIM角色漫游中&#xff0c;用户如何与建筑模型进行交互手势识别技术在BIM角色漫游中的应用有哪些图示花有重开日&#xff0c;人无再少年实践是检验真理的唯一标准 BIM 技术&#xff1a;角色漫游 编辑&#xff1…

基于ssm金旗帜文化培训学校网站的设计与开发论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对培训学校展示信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…

【云原生kubernets】Pod详解

一、Pod介绍 1.1.概念 Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管理Pod运行的State…

使用国内镜像源安装opencv

在控制台输入命令&#xff1a; pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple 验证安装&#xff1a; step 1&#xff1a; 打开终端&#xff1b;step 2&#xff1a; 输入python&#xff0c;进入Python编译环境&#xff1b;step 3&#xff1a; 粘贴…

打开软木塞,我们来谈谈葡萄酒泡泡吧

香槟是任何庆祝场合的最佳搭配。从婚礼和生日到单身派对和典型的周五晚上&#xff0c;这款气泡饮料是生活中特别聚会的受欢迎伴侣。 来自云仓酒庄品牌雷盛红酒分享你知道吗&#xff0c;你喜欢喝的那瓶香槟酒可能根本不是香槟&#xff0c;而是汽酒&#xff1f;你不是唯一一个认…

面试官:你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢

一、什么是SPA SPA&#xff08;single-page application&#xff09;&#xff0c;翻译过来就是单页应用SPA是一种网络应用程序或网站的模型&#xff0c;它通过动态重写当前页面来与用户交互&#xff0c;这种方法避免了页面之间切换打断用户体验在单页应用中&#xff0c;所有必要…

系统安全-应用威胁风险检查项及预防方案

系统安全-应用威胁风险检查项及预防方案 1、欺骗&#xff08;认证&#xff09; 2、篡改&#xff08;授权和加密&#xff09; 3、抵赖&#xff08;日志记录和数字签名&#xff09; 4、信息泄露&#xff08;敏感信息保护&#xff09; 5、特权提升 6、拒绝服务&#xff08;数据稀释…