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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言(十五)】

动态内存管理 一、为什么要有动态内存分配? 我们已经掌握的内存开辟方式有: int val 20 ; // 在栈空间上开辟四个字节 char arr[ 10 ] { 0 }; // 在栈空间上开辟 10 个字节的连续空间 但是上述的开辟空间的方式有两个特点: • 空间开辟大小是固…

leetcode LCR 173. 点名

代码&#xff1a; class Solution {public int takeAttendance(int[] records) {int left0,rightrecords.length-1;while (left<right){int midleft(right-left)/2;if(midrecords[mid]){leftmid1;}else {rightmid;}}if(leftrecords[left]){return left1;}else {return left…

北斗三号短报文+4G的低功耗太阳能船载报位监控方案

国内海洋船舶群体长期在海上航行&#xff0c;多数海员由于海面无信号覆盖、个人卫星通信费用昂贵、无法自由使用船载公用卫星通信设备等原因&#xff0c;无法与家人和朋友保持联系&#xff0c;甚至在遇到危险的时候也无法及时向外界发出求救信号&#xff0c;管理单位难以掌握船…

新钛云服助力爱达邮轮·魔都号首航,保驾护航,共创辉煌

随着2024年1月1日的临近&#xff0c;中国首艘国产大型邮轮——爱达邮轮魔都号即将迎来激动人心的首航时刻。作为爱达邮轮的IT系统运维和安全服务伙伴&#xff0c;新钛云服有幸提前登船体验&#xff0c;并为魔都号即将到来的航行提供全面的技术支持与保障。 爱达魔都号&#xff…

微积分-三角函数2

三角函数 在上一节中&#xff0c;讨论了如何在直角三角形中定义三角函数&#xff0c;限制让我们扩展三角函数的定义域。 事实上我们可以取任意角的正弦和余弦&#xff0c;而不只是局限于 0 0 0~ π 2 \frac{\pi}{2} 2π​当中。 当然需要注意的是&#xff0c;正切函数对不是对…

Git使用rebase和merge区别

Git使用rebase和merge区别 模拟环境使用merge合并使用rebase 模拟环境 本地dev分支中DevTest增加addRole() 远程dev被同事提交增加了createResource() 使用merge合并 使用idea中merge解决冲突后, 推送远程dev后,日志图显示 使用rebase idea中使用功能rebase 解决冲突…

论文解读 | NeurIPS2023:「解释一切」图像概念解释器

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 讲者简介 孙奥&#xff1a; 香港科技大学软件安全实验室在读博士&#xff0c;研究兴趣为可解释性人工智能和可信机器学习&#xff0c;主要是从Post-hoc&#xff0c;逻辑和概念的角度分析神经网络的机理 Title 「…

IntelliJ IDEA 自带的 HTTP Client接口调用插件,替代 Postman

文章目录 引言建议目录结构新建请求不同环境的变量配置添加环境http-client.env.jsonhttp-client.private.env.json引用变量 请求示例Get请求示例Post请求示例鉴权示例断言示例Websocket请求示例 内置对象和动态变量内置对象&#xff1a;内置变量&#xff1a; 引言 在日常的 W…

Eslint 要被 Oxlint替换了吗

什么是 Oxlint 由于最近的rust在前端领域的崛起,基于rust的前端生态链遭到rust底层重构,最近又爆出OxLint,是一款基于Rust的linter工具。Oxlint在国外前端圈引起热烈讨论,很多大佬给出了高度评价。 事实上,Oxlint 是 Oxc 项目旗下的一款产品,专为 JavaScript 和 TypeSc…

Python轴承故障诊断 (七)基于EMD-CNN-LSTM的故障分类

目录 前言 1 经验模态分解EMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 制作数据集和对应标签 2.3 故障数据的EMD分解可视化 2.4 故障数据的EMD分解预处理 3 基于EMD-CNN-LSTM的轴承故障诊断分类 3.1 训练数据、测试数据分组&#xff0c;数据分batch 3.…

TG-5510cb: txo高稳定性+105℃高温

TG-5510CB是一款高稳定性TCXO&#xff0c;可提供CMOS或限幅正弦输出&#xff0c;5G基站和边缘计算的额定温度为85C&#xff0c;需要室外安装、小型化和无风扇运行。与其他TCXO相比&#xff0c;实验室提供了许多改进&#xff0c;如低温度斜率和相位噪声。符合GR-1244-CORE地层3和…

ssm+vue的高校智能培训管理系统分析与设计(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的高校智能培训管理系统分析与设计&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

git 常见错误总结(会不断更新中。。)

常见错误 1. 配置部署key后git clone还是拉不下代码 执行以下命令 先添加 SSH 密钥到 SSH 代理&#xff1a; 如果你使用 SSH 代理&#xff08;例如 ssh-agent&#xff09;&#xff0c;将生成的私钥添加到代理中。 ssh-add ~/.ssh/gstplatrontend/id_rsa如果报错以下错误信息…

centos7下用yum安装包出现问题

原因&#xff1a; 这是因为yum采用Python作为命令解释器&#xff0c;这可以从/usr/bin/yum文件中第一行#!/usr/bin/python发现。而python版本之间兼容性不太好&#xff0c;使得2.X版本与3.0版本之间存在语法不一致问题。而CentOS 7自带的yum采用的是python2.7&#xff0c;当系…

3. cgal 示例 GIS (Geographic Information System)

GIS (Geographic Information System) 地理信息系统 原文地址: https://doc.cgal.org/latest/Manual/tuto_gis.html GIS 应用中使用的许多传感器&#xff08;例如激光雷达&#xff09;都会生成密集的点云。此类应用程序通常利用更先进的数据结构&#xff1a;例如&#xff0c;不…

车载以太网笔记

文章目录 以太网协议分层协议中间设备子网掩码物理层测试内容比较杂,后续会整理。 以太网协议分层 协议 中间设备

Github 2023-12-16开源项目日报Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-16统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目2非开发语言项目2TypeScript项目1Jupyter Notebook项目1Go项目1PHP项目1JavaScript项目1C#项目1 精…

初识Dubbo学习,一文掌握Dubbo基础知识文集(1)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

verilog进阶语法-触发器原语

概述: xilinx设计的触发器提供了多种配置方式&#xff0c;方便设计最简触发器&#xff0c;同步复位触发器&#xff0c;异步复位触发器&#xff0c;同步时钟使能触发器&#xff0c;异步时钟使能触发器。输出又分为同步复位和置位&#xff0c;异步清零和预置位。 官方提供的原语…

抖音视频解析,无水印解析下载抖音视频

抖音视频解析&#xff0c;你是否经常遇到这样的情况&#xff0c;看到一些非常精彩的抖音视频&#xff0c;想要保存下来&#xff0c;但因为下载速度慢或者视频带有水印而感到困扰&#xff1f;那么&#xff0c;这款&#xff08;抖音无水印解析工具&#xff09;将是你的得力助手&a…