自定义实现简版状态机
状态机(State Machine)是一种用于描述系统行为的数学模型,广泛应用于计算机科学、工程和自动化等领域。它通过定义系统的状态、事件和转移来模拟系统的动态行为。
基本概念
-
状态(State):系统在某一时刻的特定条件或模式。
-
事件(Event):触发状态转移的外部输入或条件变化。
-
转移(Transition):状态因事件而发生的改变。
-
动作(Action):在状态转移或处于某一状态时执行的操作。
简单点来说就是某一个流程当前状态A->事件1->状态B, 或者状态A->事件2->C的一个流程, 实现起来也是比较简单的
自定义状态机
基本原理就是根据状态机的概念简单实现一下, 根据读取json文件来配置整个流程
状态机配置
@Data
public class StateMachineConfig {/*** 状态机名称(Bean名称)*/private String name;/*** 状态机配置*/private List<Transition> transitions;@Datapublic static class Transition {/*** 当前状态*/private String from;/*** 事件*/private String event;/*** 下一个状态*/private String to;}
}
{"name": "orderProcess","transitions": [{"from": "A","event": "event1","to": "B"},{"from": "A","event": "event2","to": "C"},{"from": "B","event": "event3","to": "C"},{"from": "C","event": "event1","to": "D"}]
}
状态机实例
这个类主要是状态机的实例, 也是实现状态机的核心类, 主要实现为Table类, 简单点说就是两个key确定一个value
/*** 状态机实例类** @author zzt* @version 1.0.0*/
@Slf4j
public class SimpleStateMachine {/*** 状态转换关系*/private final Table<String, String, String> table = HashBasedTable.create();/*** 添加状态转换关系* 该方法用于在状态机中添加从当前状态到新状态的转换关系。转换关系由当前状态、事件和新状态组成。** @param fromState 当前状态,表示转换的起始状态。* @param event 触发状态转换的事件。* @param toState 转换后的新状态。*/public void addTransition(String fromState, String event, String toState) {table.put(fromState, event, toState);}/*** 发送事件以触发状态转换* 此方法根据当前状态和接收到的事件来确定是否需要进行状态转换* 如果当前状态和事件的组合在转换表中定义了状态转换,则执行转换* 否则,输出没有可用转换的消息** @param currentState 当前状态* @param event 触发状态转换的事件* @return 返回新状态*/public String sendEvent(String currentState, String event) {//获取下一个状态String to = table.get(currentState, event);if (StringUtils.isBlank(to)) {log.error("没有可用转换, 请检查配置文件,currentState: [{}], event: [{}]", currentState, event);throw new BusinessException("获取状态异常!");}return to;}
}
状态机工厂
状态机工厂主要就是用来生产状态机实例的, 在实际项目中可能会配置多个流程,因此需要生成多个状态机实例, 当时用时只需要从容器中获取一个实例即可
/*** 状态机实例工厂,负责创建状态机并将其注册到 Spring IOC 容器中** @author zzt* @version 1.0.0*/
@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "state-machine")
public class StateMachineFactory {/*** 是否启用状态机*/private Boolean enable = false;/*** 状态机配置文件路径(resources目录下的包)*/private String path = "";private final ApplicationContext applicationContext;/*** 初始化所有状态机并注册到 Spring IOC 容器中*/@Beanpublic void registerStateMachines() {if (enable) {// 获取所有状态机配置List<StateMachineConfig> stateMachineConfigs = StateMachineJsonUtil.readAllJsonFiles(path);// 获取状态机配置名称BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();for (StateMachineConfig config : stateMachineConfigs) {//判断是否已经存在Bean名称if (!registry.containsBeanDefinition(config.getName())) {GenericBeanDefinition beanDefinition = new GenericBeanDefinition();beanDefinition.setBeanClass(SimpleStateMachine.class);beanDefinition.setInstanceSupplier(() -> createStateMachine(config));// 使用状态机名称作为 Bean 名称registry.registerBeanDefinition(config.getName(), beanDefinition);} else {log.error("状态机名称:[{}]重复,请检查配置文件!", config.getName());throw new SpringBootPlusException("状态机名称重复,请检查配置文件!");}}}}/*** 创建并配置状态机实例** @param stateMachineConfig 状态机配置* @return 配置好的状态机实例*/private SimpleStateMachine createStateMachine(StateMachineConfig stateMachineConfig) {// 创建状态机并配置SimpleStateMachine stateMachine = new SimpleStateMachine();// 配置状态机的转换规则for (StateMachineConfig.Transition transition : stateMachineConfig.getTransitions()) {stateMachine.addTransition(transition.getFrom(), transition.getEvent(), transition.getTo());}return stateMachine;}
}
读取json文件
/*** 读取 json 文件** @author zzt* @version 1.0.0*/
@Slf4j
public class StateMachineJsonUtil {/*** 读取 resources/path 目录下的所有 .json 文件,并将其解析为 StateMachineConfig 对象的列表。** @param path json文件路径* @return 包含所有解析后的 StateMachineConfig 对象的列表*/public static List<StateMachineConfig> readAllJsonFiles(String path) {ObjectMapper objectMapper = MapperUtils.getInstance();List<StateMachineConfig> stateMachineConfigs = new ArrayList<>();try {ClassPathResource resource = new ClassPathResource(path);File[] files = resource.getFile().listFiles();if (files != null) {// 遍历每个资源文件,将其解析为 StateMachineConfig 对象并添加到列表中for (File file : files) {if (file.exists()) {FileInputStream inputStream = new FileInputStream(file);StateMachineConfig stateMachineConfig = objectMapper.readValue(inputStream, StateMachineConfig.class);stateMachineConfigs.add(stateMachineConfig);}}}} catch (Exception e) {log.error("读取json文件失败,[{}]", e.getMessage(), e);throw new SpringBootPlusException("读取json文件失败");}return stateMachineConfigs;}
}
相关文章:
自定义实现简版状态机
状态机(State Machine)是一种用于描述系统行为的数学模型,广泛应用于计算机科学、工程和自动化等领域。它通过定义系统的状态、事件和转移来模拟系统的动态行为。 基本概念 状态(State):系统在某一时刻的特…...

算法常见八股问题整理
1.极大似然估计和交叉熵有什么关系 在分类问题中,当我们使用softmax函数作为输出层时,最大化对数似然函数实际上等价于最小化交叉熵损失函数。具体来说,在多分类情况下,最大化该样本的对数似然等价于最小化该样本的交叉熵损失。 交…...
关于GeoPandas库
geopandas buildings gpd.read_file(shapefile_path) GeoDataFrame 对象有一个属性叫做 sindex 空间索引通常是基于 R-树 或其变体构建的,这些数据结构专为空间查询优化,可以显著提高查询效率,尤其是在处理大型数据集时。 buildings_sin…...

【漫话机器学习系列】103.学习曲线(Learning Curve)
学习曲线(Learning Curve)详解 1. 什么是学习曲线? 学习曲线(Learning Curve)是机器学习和深度学习领域中用于评估模型性能随训练过程变化的图示。它通常用于分析模型的学习能力、是否存在过拟合或欠拟合等问题。 从…...

电商运营中私域流量的转化与变现:以开源AI智能名片2+1链动模式S2B2C商城小程序为例
摘要 电商运营的核心目标在于高效地将产品推向市场,实现私域流量的转化和变现。本文以“罗辑思维”的电商实践为背景,探讨了私域流量变现的重要性,并深入分析了开源AI智能名片21链动模式S2B2C商城小程序在电商运营中的应用与价值。通过该模式…...
Python常见面试题的详解19
1. 如何使用Django 中间件 Django 中间件宛如一个灵活且强大的插件系统,它为开发者提供了在请求处理流程的不同关键节点插入自定义代码的能力。这些节点包括请求抵达视图之前、视图完成处理之后以及响应即将返回给客户端之前。借助中间件,我们可以实现诸…...
Python 数据类型转换
目录 整数(int)与浮点数(float)之间的转换 (1)int():将浮点数或字符串转换为整数 (2)float():将整数或字符串转换为浮点数 字符串(str…...

进程概念、PCB及进程查看
文章目录 一.进程的概念进程控制块(PCB) 二.进程查看通过指令查看进程通过proc目录查看进程的cwd和exe获取进程pid和ppid通过fork()创建子进程 一.进程的概念 进程是一个运行起来的程序,而程序是存放在磁盘的,cpu要想执行程序的指…...
PyEcharts 数据可视化:从入门到实战
一、PyEcharts 简介 PyEcharts 是基于百度开源可视化库 ECharts 的 Python 数据可视化工具,支持生成交互式的 HTML 格式图表。相较于 Matplotlib 等静态图表库,PyEcharts 具有以下优势: 丰富的图表类型(30)动态交互功…...

RT-Thread+STM32L475VET6——ADC采集电压
文章目录 前言一、板载资源二、具体步骤1.打开CubeMX进行配置1.1 使用外部高速时钟,并修改时钟树1.2 打开ADC1的通道3,并配置为连续采集模式(ADC根据自己需求调整)1.3 打开串口1.4 生成工程 2. 配置ADC2.1 打开ADC驱动2.2 声明ADC2.3 剪切stm…...

easyexcel 2.2.6版本导出excel模板时,标题带下拉框及其下拉值过多不显示问题
需求背景:有一个需求要做下拉框的值有100多条,同时这个excel是一个多sheet的导入模板 直接用easyexcel 导出,会出现下拉框的值过多,导致生成出来的excel模板无法正常展示下拉功能 使用的easyexcel版本:<depende…...

树(数据结构·)
树(数据结构篇) 里面没有结点时,称之为空树 树型结构是一对多的形式 深度优先遍历: 所谓的DFS,也就是说每次都尝试向更深的节点走,也就是一条路走到黑 当一条路走完,走到…...
XUnity.AutoTranslator-deepseek——调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译
XUnity.AutoTranslator-deepseek 本项目通过调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译。 准备工作 1. 获取API密钥 访问腾讯云API控制台申请DeepSeek的API密钥(限时免费)。也可以使用其他平台提供的DeepSeek API。 …...

谈谈 ES 6.8 到 7.10 的功能变迁(1)- 性能优化篇
前言 ES 7.10 可能是现在比较常见的 ES 版本。但是对于一些相迭代比较慢的早期业务系统来说,ES 6.8 是一个名副其实的“钉子户”。 借着工作内升级调研的任务东风,我整理从 ES 6.8 到 ES 7.10 ELastic 重点列出的新增功能和优化内容。将分为 6 个篇幅给…...

[250222] Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡 | SQLPage v0.33 发布
目录 Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡SQLPage v0.33 发布:使用 SQL 构建自定义 UI 和 API! Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡 Kimi 开放平台推出全新模型 kimi-latest,旨在…...
深入理解设计模式之解释器模式
深入理解设计模式之解释器模式 在软件开发的复杂世界中,我们常常会遇到需要处理特定领域语言的情况。比如在开发一个计算器程序时,需要解析和计算数学表达式;在实现正则表达式功能时,要解析用户输入的正则表达式来匹配文本。这些场景都涉及到对特定语言的解释和执行,而解…...
深入理解设计模式之代理模式
深入理解设计模式之代理模式 在软件开发的复杂体系中,我们常常会遇到这样的情况:需要控制对某个对象的访问,或者在访问对象前后添加一些额外的处理逻辑,又或者希望在不改变原对象代码的基础上扩展其功能。代理模式(Pr…...

Golang | 每日一练 (3)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...

企业数据集成:实现高效调拨出库自动化
调拨出库对接调出单-v:旺店通企业奇门数据集成到用友BIP 在企业信息化管理中,数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例,展示如何通过轻易云数据集成平台,将旺店通企业奇门的数据无缝集成到用…...

提效10倍:基于Paimon+Dolphin湖仓一体新架构在阿里妈妈品牌业务探索实践
1. 业务背景 阿里妈妈品牌广告数据包括投放引擎、下发、曝光、点击等日志,面向运筹调控、算法特征、分析报表、诊断监控等应用场景,进行了品牌数仓能力建设。随着业务发展,基于Lambda架构的数仓开发模式,缺陷日益突出:…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...

MeshGPT 笔记
[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭!_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...