还在用ifelse来写业务?了解下Spring状态机

news2025/3/13 6:58:06

在这里插入图片描述

状态机之所以强大,是因为其行为在启动时就以固定的方式定义了操作规则,从而确保了一贯的连贯性和相对较高的可调试性。关键在于,应用程序处于且仅可能处于有限数量的状态中。然后,某些事件发生会使得应用从一个状态过渡到另一个状态。状态机由触发器驱动,这些触发器基于事件或计时器。

设计高层次逻辑并将其置于应用程序外部,然后通过多种方式与状态机交互,这种方式要简单得多。可以通过发送事件、监听状态机的行为或请求当前状态来与状态机进行交互。

当开发者意识到代码库开始变得般混乱不堪时,就会在现有项目中引入状态机。面条代码表现为无尽的、层级化的IF、ELSE和BREAK子句结构,当事情变得过于复杂时,编译器或许应该建议开发者暂停一下,先休息一下。状态机的引入有助于将复杂多变的应用程序状态转换过程组织得更为有序和清晰,从而避免代码陷入难以维护的境地。

什么是状态

状态是状态机可能处于的一种模型。相比于在通用文档中使用抽象概念,通过现实生活中的例子来描述状态通常更为直观易懂。以一个简单的键盘为例——我们大多数人每天都使用它。如果你有一个标准键盘,左侧有普通键,右侧有数字小键盘,你可能会注意到,根据Numlock(数字锁定)是否激活,数字小键盘可以处于两种不同的状态。如果没有激活,按下数字小键盘的按键会实现方向导航等功能;如果数字小键盘被激活,则按下这些键将输入数字。本质上,键盘的数字小键盘部分可以处于两种不同的状态。

将状态的概念联系到编程上,这意味着我们可以不再依赖于标志位、嵌套的if/else/break语句或其他不切实际(有时甚至是曲折复杂的)逻辑,而是可以通过状态、状态变量或与状态机的交互来处理问题。换句话说,在编程中运用状态这一概念,能够帮助我们更清晰地组织和管理程序的不同状态及其转换过程。

什么是状态机

状态机是一种理论模型,它描述了一个对象在其生命周期内可能经历的有限数量的状态及其之间的转换规则。每个状态都有触发状态迁移的条件(通常是事件),并且可以关联执行的动作。

状态机的核心在于状态变迁和事件驱动,适合处理异步和并发的情况。状态机强调的是系统当前所处的状态,并且关注于系统如何根据接收到的外部事件或内部条件进行状态转变。

状态机最常见于嵌入式系统、用户界面交互设计、游戏开发、网络协议解析等领域。

以下以游戏马里奥的状态切换为例,来理解状态机的使用场景:

吃蘑菇
吃花
被敌人碰到
被敌人碰到
小马里奥
超级马里奥
火焰马里奥

与状态设计模式的区别

在面向对象编程中,状态设计模式是一种行为型设计模式,允许对象在其内部状态改变时改变其行为。该模式通过将每一个状态封装成一个类,使得当对象的状态发生改变时,它的行为也随之改变,同时能够使代码更加清晰和模块化。

在状态设计模式中,每个状态是一个单独的类实例,这些类通常会实现一个公共接口,以便上下文对象可以调用适当的方法,而无需知道具体当前处于哪种状态。上下文对象(context)持有对当前状态对象的引用,并在接收到特定事件时调用状态对象的方法来处理事件并可能导致状态切换。

联系

  • 状态设计模式是对状态机理论的一种实现,它把状态机的概念应用于软件设计中,利用面向对象技术实现了状态的抽象、封装和扩展性。

区别

  • 状态机是一个抽象的概念,可以不依赖于任何特定的编程语言或设计模式独立存在。
  • 状态设计模式则是具体的编程实践,是针对解决状态转换问题的一种设计解决方案,特别适用于面向对象环境下的复杂状态管理。

与流程引擎的区别

**流程引擎(Business Process Management Engine, BPMN Engine)**是实现业务流程管理(BPM)的软件组件,主要用于执行和监控预定义的工作流程。这些工作流程通常包括一系列顺序执行的任务或活动,具有明确的开始点、结束点和中间过程。

流程引擎支持更复杂的流程结构,如并行分支、同步合并、循环等,并提供了丰富的建模语言(如BPMN)来可视化表示流程逻辑。流程引擎不仅关注状态转移,还注重任务分配、资源调度、事务处理以及流程实例的整体生命周期管理。

流程引擎适用于企业级应用中需要自动化、规范化和优化的复杂业务流程,比如采购审批流程、贷款审批流程、订单处理流程等。

区别与联系:

  • 目的性不同: 状态机主要解决状态变化的问题,而流程引擎则更多地关注流程的整体组织和执行。
  • 结构灵活性: 状态机结构相对简单,特别适合清晰、固定的流程;流程引擎支持多层次、多路径的复杂流程,允许动态调整和扩展。
  • 参与角色: 状态机侧重于机器层面的自动化处理,流程引擎则常涉及人的参与决策和协同工作。
  • 集成度: 流程引擎通常包含更多的管理和监控功能,能够与组织其他系统紧密集成,提供强大的审计跟踪、异常处理和数据分析能力。
  • 联系: 在实际项目中,状态机的概念和机制可能会作为流程引擎的一部分被采用,尤其是在流程中有明显的状态变迁环节时。同时,两者都可以用作业务规则和流程规范的有效工具,只不过各自聚焦的领域和复杂程度有所差异。

什么是Spring状态机

Spring Statemachine(SSM)是一个框架,允许应用程序开发者在Spring应用中使用传统的状态机概念。SSM提供了以下功能:

  1. 为简单用例提供易于使用的单层(一级)状态机。
  2. 采用分层状态机结构,便于配置复杂状态。
  3. 状态机区域以支持更为复杂的状态配置。
  4. 支持触发器、转换、守卫和动作的使用。
  5. 提供类型安全的配置适配器。
  6. 集成了状态机事件监听器。
  7. 与Spring IoC(控制反转)集成,可将Bean关联至状态机。

SSM有哪些使用场景

项目适于使用状态机的场景包括:

  1. 当你可以将应用程序或其部分结构表示为一系列状态时,该项目是应用状态机的良好候选者。
  2. 你希望将复杂的逻辑拆分为更小、更易于管理的任务。
  3. 应用程序已经存在并发问题,例如异步操作导致的问题。

在以下情况下,实际上你已经在尝试实现一个状态机:

  1. 使用布尔标志或枚举来模拟各种情况。这意味着你的代码可能在通过这些标志和枚举跟踪不同状态。
  2. 拥有仅在应用程序生命周期中的某些阶段才有意义的变量。这暗示了状态变化对程序流程的影响。
  3. 正在循环遍历if-else结构(或者更糟糕的是,多个这样的结构),检查特定标志或枚举是否已设置,然后根据这些标志和枚举是否存在及其组合进一步判断接下来的操作。这种编程方式本质上是在手动处理状态转移,而采用状态机可以更清晰、规范地表述并简化此类复杂的状态转换逻辑。

如何集成SSM

需要在maven或者gradle中ssm的依赖。

<dependency>
    <groupId>org.springframework.statemachine</groupId>
    <artifactId>spring-statemachine-starter</artifactId>
    <version>4.0.0</version>
</dependency>
implementation 'org.springframework.statemachine:spring-statemachine-starter:4.0.0'

如何使用SSM

下面以一个简单的例子来说明如何使用SSM。

// 定义对应状态和事件的枚举:
public enum States {
    SI, S1, S2
}

public enum Events {
    E1, E2
}

// 定义状态机的配置
import java.util.EnumSet;

@Configuration // 标识为配置类
@EnableStateMachine // 启用状态机功能
public class StateMachineConfig
        extends EnumStateMachineConfigurerAdapter<States, Events> {

    /**
     * 配置状态机的全局属性,如自动启动和状态监听器。
     *
     * @param config 状态机配置构建器
     * @throws Exception 如果配置过程中发生错误
     */
    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Events> config)
            throws Exception {
        config
                .withConfiguration()
                .autoStartup(true) // 设置状态机自动启动
                .listener(listener()); // 注册状态改变监听器
    }

    /**
     * 配置状态机的状态。
     *
     * @param states 状态配置构建器
     * @throws Exception 如果配置过程中发生错误
     */
    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states
                .withStates()
                .initial(States.SI) // 设置初始状态为SI
                .states(EnumSet.allOf(States.class)); // 将所有枚举状态添加到状态机
    }

    /**
     * 配置状态机的转换。
     *
     * @param transitions 转换配置构建器
     * @throws Exception 如果配置过程中发生错误
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
            throws Exception {
        transitions
                .withExternal() // 配置外部触发的转换
                .source(States.SI).target(States.S1).event(Events.E1) // 定义从SI到S1的转换,由事件E1触发
                .and() // 连接另一个转换配置
                .withExternal() // 另一个外部触发的转换
                .source(States.S1).target(States.S2).event(Events.E2); // 定义从S1到S2的转换,由事件E2触发
    }

    /**
     * 创建并返回一个状态机监听器,用于监听状态的改变。
     *
     * @return 状态机监听器实例
     */
    @Bean
    public StateMachineListener<States, Events> listener() {
        return new StateMachineListenerAdapter<States, Events>() {
            @Override
            public void stateChanged(State<States, Events> from, State<States, Events> to) {
                if(from != null){
                    System.out.println("State change from " + from.getId());
                }
                System.out.println("State change to " + to.getId());
            }
        };
    }
}

测试代码如下:

@RestController
@Tag(name = "状态机", description = "状态机")
public class StateController{
    @Autowired
    private StateService stateService;

    @GetMapping(value = "改变状态")
    @Operation(description = "改变状态")
    public void change() {
        stateService.changeState();
    }
}
/**
 * 状态机演示服务
 */
@Service
public class StateService {
    @Autowired
    private StateMachine<States, Events> stateMachine;

    public void changeState() {
        stateMachine.sendEvent(Events.E1);
        stateMachine.sendEvent(Events.E2);
    }
}

服务层的输出的结果如下:

State change to SI
State change from SI
State change to S1
State change from S1
State change to S2

以上代码只是简单演示了SSM的集成和使用demo。实际业务场景可能更为复杂,需要根据实际需求进行扩展。

除了状态,要更好的使用SSM还需要理解伪状态等很多概念,比如Junction(允许多个传入转换)、 Fork(一个或多个区域的显式入口)、Join (将源自不同区域的多个过渡合并在一起)。这部分内容将在后续文章中进行介绍。

参考

  • A State Machine Crash Course - spring-statemachine https://docs.spring.io/spring-statemachine/docs/4.0.0/reference/index.html#crashcourse

关于作者

来自一线全栈程序员nine的八年探索与实践,持续迭代中。欢迎关注公众号“雨林寻北”或添加个人卫星codetrend(备注技术)。

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

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

相关文章

RuoYi-Vue使用RestTemplate无法通过@Autowired注入报错

A component required a bean of type org.springframework.web.client.RestTemplate that could not be found. 解决方法&#xff1a; 将ruoyi-framework模块下找到ApplicationConfig这个配置类使用Bean注入&#xff1a; /*** RestTemplate配置*/Beanpublic RestTemplate r…

基于数据库的全文检索实现

对于内容摘要&#xff0c;信件内容进行全文检索 基于SpringBoot 2.5.6Postgresqljpahibernate实现 依赖 <spring-boot.version>2.5.6</spring-boot.version> <hibernate-types-52.version>2.14.0</hibernate-types-52.version><dependency><…

Chrome浏览器滚动条样式优化

针对Chrome浏览器&#xff0c;可以全局设置滚动条样式&#xff0c;让你的项目更美观 ::-webkit-scrollbar-track-piece {background-color: transparent; } ::-webkit-scrollbar {width: 7px;height: 7px;background-color: transparent; }::-webkit-scrollbar-thumb {border-…

ctfshow(WEB AK赛)

目录 web-观己 web1-观字 web2-观星 web3-观图 web4-观心 过程and分析 web-观己 没啥难的有include 想着伪协议 但是过滤了php 那就是用file为协议读取本地文件 全靠猜 <?php if(isset($_GET[file])){$file $_GET[file];if(preg_match(/php/i, $file)){die(error);}…

【深度学习笔记】9_5 多尺度目标检测

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 9.5 多尺度目标检测 在9.4节&#xff08;锚框&#xff09;中&#xff0c;我们在实验中以输入图像的每个像素为中心生成多个锚框。这些…

opencv中的图像高斯双边模糊—bilateralFilter函数

高斯双边滤波&#xff08;Bilateral Filtering&#xff09;是一种非线性的滤波方法&#xff0c;用于平滑图像&#xff0c;同时保留边缘。与传统的高斯模糊不同&#xff0c;双边滤波在平滑图像的同时&#xff0c;能够避免模糊边缘。这是通过考虑像素值的差异来实现的&#xff1a…

把 Windows 装进 Docker 容器里

本篇文章聊聊如何在 Docker 里运行 Windows 操作系统&#xff0c; Windows in Docker Container&#xff08;WinD&#xff09;。 写在前面 我日常使用 macOS 和 Ubuntu 来学习和工作&#xff0c;但是时不时会有 Windows 使用的场景&#xff0c;不论是运行某个指定的软件&…

YOLOv8_pose-Openvino和ONNXRuntime推理【CPU】

纯检测系列&#xff1a; YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv7-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 跟踪系列&#xff1a; YOLOv5/6/7-O…

Fix a Tree(树的遍历,判断是否有环 并连成一颗树 )

题意翻译 对于下图中的树&#xff0c; 可以用数组表示为 [2,3,3,2]。这种可以表示树的数组&#xff08;即有效&#xff09;需要符合以下条件&#xff1a; 有且只有一个索引 r &#xff0c;符合pr​r 。其中顶点 r 是树的根。对于所有剩下的 n−1 个顶点 i 一定要有在 i 和 pi…

怎么制作自己的微信小程序店铺?

移动互联网的迅猛发展&#xff0c;微信小程序已成为商家拓展线上业务的重要工具。它不仅能够提供便捷的用户访问体验&#xff0c;还能够帮助商家快速构建起一个功能齐全的在线商城。那么&#xff0c;商家怎么制作自己的微信小程序店铺&#xff1f; 一、准备工作&#xff1a; …

鸿蒙 Harmony 初体验

前言 看现在网上传得沸沸扬扬的鸿蒙&#xff0c;打算弄个 hello world 玩一下, 不然就跟不上时代的发展了 环境安装 我的环境 Windows 11 家庭中文版HarmonyOS SDK (API 9)DevEco Studio (3.1.1 Release)Node.js (16.19.1) 开发IDE下载 官方下载链接 配置 nodejs 这里帮…

MWC 2024|「Paraverse平行云」展示空间计算时代沉浸式交互体验

&#x1f389;当地时间2月26日&#xff0c;2024年世界移动通信大会&#xff08;MWC2024&#xff09;在巴塞罗那拉开帷幕。作为全球移动通信领域最大的技术展会之一&#xff0c;MWC被视为全球通信行业风向标。 &#x1f680;随着Vision Pro再次点燃全球空间计算技术热情&#xf…

电脑文件msvcr100.dll丢失的多种解决方法,快速修复dll报错问题

当计算机用户遇到“msvcr100.dll丢失”的问题时&#xff0c;可能会感到困扰并急于寻求解决方案。这个提示通常意味着系统中某个关键的动态链接库文件缺失&#xff0c;这可能导致某些应用程序无法正常启动或运行。msvcr100.dll是Microsoft Visual C Redistributable Package的一…

HarmonyOS应用开发-Stage模型开发概述

基本概念 UI框架 HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。提供了应用UI开发所必需的能力&#xff1a;多种组件、布局计算、动画能力、UI交互、绘制。 方舟开发框架针对开发者提供了两种开发范式&#xff1a; 基于ArkTS…

Java实现知乎热点小时榜爬虫

1.效果演示 1.1 热点问题列表 启动程序后&#xff0c;自动展示热点问题&#xff0c;并等待终端输入 1.2 根据序号选择想看的热点问题 输入问题序号&#xff0c;展示回答内容 1.3 退出 输入q即可退出程序 2.源码 2.1 pom.xml <?xml version"1.0" enco…

【机器学习】无监督学习算法之:层次聚类

层次聚类 1、引言2、层次聚类2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 这周末过的滋润啊。 小鱼&#xff1a;… 每个周末都挺滋润的啊。 小屌丝&#xff1a;啊~ ~ 你这… 小鱼&#xff1a;周末加班&#xf…

从大厂到高校,鸿蒙人才“红透半边天”!

截至目前&#xff0c;继清华大学、北京航空航天大学、武汉大学等985高校开设鸿蒙相关课程后&#xff0c;已经或将要开设鸿蒙相关课程的985、211高校达到近百所&#xff0c;为鸿蒙人才培养提供沃土。 随着鸿蒙系统即将摒弃安卓&#xff0c;鸿蒙原生应用将全面启动的背景下&…

win10从Huggingface下载模型

这里写自定义目录标题 安装CLI工具设置环境变量下载 安装CLI工具 安装Huggingface CLI pip install -U huggingface_hub设置环境变量 设置好变量后&#xff0c;重新启动一个新的命令窗口&#xff0c;cmd或者powershell 下载 huggingface-cli download --resume-download fa…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的安全帽检测系统(深度学习模型+UI界面代码+训练数据集)

摘要&#xff1a;开发先进的安全帽识别系统对提升工作场所的安全性至关重要。本文详细介绍了使用深度学习技术创建此类系统的方法&#xff0c;并分享了完整的实现代码。系统采用了强大的YOLOv8算法&#xff0c;并对其与YOLOv7、YOLOv6、YOLOv5的性能进行了详细比较&#xff0c;…

mysql数据库:使用 bash脚本 + 定时任务 自动备份数据

mysql数据库&#xff1a;使用 bash脚本 定时任务 自动备份数据 1、前言2、为什么需要自动化备份&#xff1f;3、编写备份脚本4、备份脚本授权5、添加定时任务6、重启 crond / 检查 crond 服务状态7、备份文件检查 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏…