面试官竟然是个小黑子,问我用过状态机吗

状态机的组成

状态机是一种抽象的数学模型,描述了对象或系统在特定时间点可能处于的各种状态以及状态之间的转换规则。它由一组状态、事件、转移和动作组成,用于模拟对象在不同条件下的行为和状态变化。

image-20240423094124100

状态机包括以下基本组成部分:

  • 状态(State):表示对象或系统当前的状态,例如开、关、就绪等。
  • 事件(Event):触发状态转换的动作或条件,例如按钮点击、消息到达等。
  • 转移(Transition):定义了从一个状态到另一个状态的转换规则,通常与特定事件相关联。
  • 动作(Action):在状态转换过程中执行的操作或行为,例如更新状态、记录日志等。

状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型。说白了,一般就是指一张状态转换图。例如,根据自动门的运行规则,我们可以抽象出下面这么一个图。

image-20240423095540911

简单实现

在计算机中,状态机通常用编程语言来实现。在 C、C++、Java、Python 等编程语言中,可以通过使用 switch-case 语句、if-else 语句、状态转移表等来实现状态机。在下面还有更加优雅的方式,使用 Spring 状态机 来实现。

if-else 实现状态机

在上面的示例中,我们使用 if-else 结构根据当前活动来控制音乐的播放状态,并执行相应的行为。代码如下:

public class BasketballMusicStateMachineUsingIfElse {private boolean isPlayingMusic;public BasketballMusicStateMachineUsingIfElse() {this.isPlayingMusic = false; // 初始状态为音乐未播放}public void playMusic() {if (!isPlayingMusic) {System.out.println("Music starts playing...");isPlayingMusic = true;}}public void stopMusic() {if (isPlayingMusic) {System.out.println("Music stops playing...");isPlayingMusic = false;}}public void performActivity(String activity) {if ("basketball".equals(activity)) {System.out.println("Music~");playMusic(); // 打篮球时播放音乐} else if ("sing_rap".equals(activity)) {System.out.println("哎哟你干嘛!");stopMusic(); // 唱跳Rap时停止音乐} else {System.out.println("Invalid activity!");}}public static void main(String[] args) {BasketballMusicStateMachineUsingIfElse stateMachine = new BasketballMusicStateMachineUsingIfElse();// 测试状态机stateMachine.performActivity("basketball"); // 打篮球,音乐开始播放stateMachine.performActivity("sing_rap"); // 唱跳Rap,音乐停止播放stateMachine.performActivity("basketball"); // 再次打篮球,音乐重新开始播放}
}
switch-case 实现状态机

在这个示例中,我们使用 switch-case 结构根据不同的活动来控制音乐的播放状态,并执行相应的行为。代码如下:

public class BasketballMusicStateMachineUsingSwitchCase {private boolean isPlayingMusic;public BasketballMusicStateMachineUsingSwitchCase() {this.isPlayingMusic = false; // 初始状态为音乐未播放}public void playMusic() {if (!isPlayingMusic) {System.out.println("Music starts playing...");isPlayingMusic = true;}}public void stopMusic() {if (isPlayingMusic) {System.out.println("Music stops playing...");isPlayingMusic = false;}}public void performActivity(String activity) {switch (activity) {case "basketball":System.out.println("Music ~");playMusic(); // 打篮球时播放音乐break;case "sing_rap":System.out.println("哎哟 你干嘛 ~");stopMusic(); // 唱跳Rap时停止音乐break;default:System.out.println("Invalid activity!");}}public static void main(String[] args) {BasketballMusicStateMachineUsingSwitchCase stateMachine = new BasketballMusicStateMachineUsingSwitchCase();// 测试状态机stateMachine.performActivity("basketball"); // 打篮球,音乐开始播放stateMachine.performActivity("sing_rap"); // 唱跳Rap,音乐停止播放stateMachine.performActivity("basketball"); // 再次打篮球,音乐重新开始播放}
}

是不是感觉状态机其实经常在我们的日常使用中捏~,接下来带大家使用更优雅的状态机 Spring 状态机。

image-20240423100302874
使用 Spring 状态机

1)引入依赖

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.0.1.RELEASE</version>
</dependency>

2)定义状态和事件的枚举

代码如下:

public enum States {IDLE,       // 空闲状态PLAYING_BB, // 打篮球状态SINGING     // 唱跳Rap状态
}
public enum Event {START_BB_MUSIC, // 开始播放篮球音乐事件STOP_BB_MUSIC   // 停止篮球音乐事件
}

3)配置状态机

代码如下:

@Configuration
@EnableStateMachine
public class BasketballMusicStateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Event> {@Autowiredprivate BasketballMusicStateMachineEventListener eventListener;@Overridepublic void configure(StateMachineConfigurationConfigurer<States, Event> config) throws Exception {config.withConfiguration().autoStartup(true).listener(eventListener); // 设置状态机事件监听器}@Overridepublic void configure(StateMachineStateConfigurer<States, Event> states) throws Exception {states.withStates().initial(States.IDLE).states(EnumSet.allOf(States.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<States, Event> transitions) throws Exception {transitions.withExternal().source(States.IDLE).target(States.PLAYING_BB).event(Event.START_BB_MUSIC).and().withExternal().source(States.PLAYING_BB).target(States.SINGING).event(Event.STOP_BB_MUSIC).and().withExternal().source(States.SINGING).target(States.PLAYING_BB).event(Event.START_BB_MUSIC);}
}

4)定义状态机事件监听器

代码如下:

@Component
public class BasketballMusicStateMachineEventListener extends StateMachineListenerAdapter<States, Event> {@Overridepublic void stateChanged(State<States, Event> from, State<States, Event> to) {if (from.getId() == States.IDLE && to.getId() == States.PLAYING_BB) {System.out.println("开始打篮球,music 起");} else if (from.getId() == States.PLAYING_BB && to.getId() == States.SINGING) {System.out.println("唱跳,你干嘛");} else if (from.getId() == States.SINGING && to.getId() == States.PLAYING_BB) {System.out.println("继续打篮球,music 继续");}}
}

5)编写单元测试

@SpringBootTest
class ChatApplicationTests {@Resourceprivate StateMachine<States, Event> stateMachine;@Testvoid contextLoads() {//开始打球,music 起stateMachine.sendEvent(Event.START_BB_MUSIC);//开始唱跳,你干嘛stateMachine.sendEvent(Event.STOP_BB_MUSIC);//继续打球,music 继续stateMachine.sendEvent(Event.START_BB_MUSIC);}
}

效果如下:

image-20240423103523546

在上面的示例中,我们定义了一个状态机,用于控制在打篮球时音乐的播放和唱跳 Rap 的行为。通过触发事件来执行状态转移,并通过事件监听器监听状态变化并执行相应的操作。

image-20240423103604502

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

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

相关文章

【IR 论文】Query2doc — 使用 LLM 做 Query Expansion 来提高信息检索能力

论文&#xff1a;Query2doc: Query Expansion with Large Language Models ⭐⭐⭐⭐⭐ Microsoft Research, EMNLP 2023 文章目录 背景介绍Query2doc 论文速读实现细节实验结果和分析总结分析 背景介绍 信息检索&#xff08;Information Retrieval&#xff0c;IR&#xff09;指…

数据清洗:异常值检测方法

异常值检测方法总结 一、基于分布1、3σ原则2、Z_score方法3、boxplot一、基于分布 1、3σ原则 3σ原则又称为拉依达法则。该法则就是先假设一组检测数据只含有随机误差,对原始数据进行计算处理得到标准差,然后按一定的概率确定一个区间,认为误差超过这个区间的就属于异常…

使用 IPAM 解决方案简化分布式网络管理

随着组织在数字领域的全球扩张&#xff0c;分布式网络是不可避免的&#xff0c;这意味着&#xff0c;随着 IT 基础设施的发展&#xff0c;组织需要适应&#xff0c;这包括在不断增长的系统需求、应用程序堆栈、各种协议和安全防御中监控、现代化和简化流程和资源。在有效管理现…

【Java框架】SpringBoot(二)核心配置

目录 yml文件什么是yml文件yml文件的优点使用场景脚本语言序列化配置文件 yml的基本语法yml支持的数据类型字面量对象(属性和值)、Map(键值对)数组复合结构 Spring Boot配置文件的值注入第一种读取方式Value第二种读取方式ConfigurationProperties第三种读取方式自动装配Enviro…

【大模型书籍】从零开始大模型开发与微调:基于PyTorch与ChatGLM(附PDF)

哈喽各位&#xff0c;今天又来给大家分享大模型学习书籍了&#xff0c;今天是这本<从零开始大模型开发与微调&#xff1a;基于PyTorch与ChatGLM 书籍PDF分享>&#xff0c;大模型是深度学习自然语言处理皇冠上的一颗明珠&#xff0c;也是当前AI和NLP研究与产业中最重要的方…

Pushmall智能AI数字名片— —寻求商机合作的营销推广平台

Pushmall智能AI数字名片— —寻求商机合作的营销推广平台 开发计划 2024年2月开发计划&#xff1a; 1、优化名片注册、信息完善业务流程&#xff1b; 2、重构商机信息&#xff1a;供应信息、需求信息发布。 3、会员名片服务优化 4、企业名片&#xff1a;员工管理优化 5、CRM客…

Linux之 USB驱动框架-USB总线(2)

一、linux 下&#xff0c;通过系统查看usb 总线 ls /sys/bus/usb/devices/也包含了很多信息&#xff1a; 其中usb1、usb2代表系统注册了2条usb总线&#xff0c;即有2个USB主机控制器&#xff0c;1和2用于区分不同总线&#xff0c;是USB的总线号。 每插入一个usb设备&#xff…

Java中创建对象内存分析

package day31; ​ public class Pet {String name;int age;public void shout(){System.out.println("叫了一声");} } ​ package day31; ​ public class Application {public static void main(String[] args) {Pet cat new Pet();cat.name"肥波";cat…

数据分析专家能力模型

招式&#xff1a;懂商业&#xff08;业务能力&#xff09; 外功更偏重于技能&#xff0c;首先需要懂招式&#xff0c;即懂商业&#xff0c;数据分析最终是为业务服务的&#xff0c;无论是互联网企业准求的用户增长和UJM分解&#xff0c;还是传统企业追求的降本增效和精细化运营…

赛氪网凭借教育人优势,荣获中关村高新技术企业协会会员单位称号

2023年&#xff0c;中关村科技园区管理委员会正式公布了一批新的高新技术企业协会会员单位名单&#xff0c;赛氪网荣幸成为其中一员。这一荣誉的获得&#xff0c;不仅是对赛氪网在竞赛、科技创新教育领域的充分肯定&#xff0c;也标志着赛氪网在推动高新技术发展方面迈出了坚实…

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡 配置ssh远程连接docker1.端口映射2.配置ssh 在docker中使用nvidia显卡配置CUDA 注意&#xff1a;之前已经创建过容器的&#xff0c;需要打包成镜像&#xff0c;重新创建容器&#xff0c;因为要在创建…

【ONE·基础算法 || 递归 二叉树深搜】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解递归类题型&#xff0c;进一步加深理解深搜&#xff0c;引入回溯和剪枝相关概念。       1、递归 1&#xff09;、递归   实际在学习语言中我们对其有一定涉及。这里&#xff0c;若从宏观视角看待递归的过程&am…

每日OJ题_BFS解决拓扑排序①_力扣207. 课程表

目录 拓扑排序和图的介绍 ①力扣207. 课程表 解析代码 拓扑排序和图的介绍 拓扑排序简单来说就是找到做事情的先后顺序&#xff08;拓扑排序的结果可能不是唯一的&#xff09;。 学习拓扑排序前先简单学习图的基本概念&#xff1a; 图是由顶点集合及顶点间的关系组成的一种…

牛客网刷题 | BC60 判断是不是字母

描述 KiKi想判断输入的字符是不是字母&#xff0c;请帮他编程实现。 输入描述&#xff1a; 多组输入&#xff0c;每一行输入一个字符。 输出描述&#xff1a; 针对每组输入&#xff0c;输出单独占一行&#xff0c;判断输入字符是否为字母&#xff0c;输出内容详见输出样例…

国标GB28181协议EasyGBS视频监控平台设备报错“callid[924517228] cseq”,是什么原因?

国标视频云服务EasyGBS支持设备/平台通过国标GB28181协议注册接入&#xff0c;并能实现视频的实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强&#xff0c;支持将接入的视频流进行全终端、全平台分发&#xff0c;分发的视频…

106短信群发平台如此火热究竟有没有效?

106短信群发平台之所以如此火热&#xff0c;确实是因为它在多个方面展现出了显著的有效性。 首先&#xff0c;从发送速度和到达率来看&#xff0c;106短信平台表现优秀。无论是节假日还是平日&#xff0c;其发送速度都能保持在一个较快的水平&#xff0c;这对于验证码短信、通…

Python语言第二章之控制流程(判断,循环)

判断 1. if 语句 if 语句语法: if 判断的条件: 条件成立时, 执行的代码 flag False if flag True:print("hhh")age 19 if age > 18:print("可以上网了! ") 2. if-else 语句 定义一个整数, 记录年龄 判断是否满18 如果满18, 允许进网吧 age int(in…

PDF 书签制作与调整

本文是对以前发表的旧文拆分&#xff0c;因为原文主题太多&#xff0c;过长&#xff0c;特另起一篇分述。 第一部分 由可编辑 PDF 文档创建书签 方法 1. Adobe Acrobat Pro autobookmark AutoBookmark 是一个可用于 Adobe Acrobat 自动生成书签的插件。 官方下载地址&…

【Canvas与艺术】绘制金色八卦图

【关键点】 等比例缩放各部件及将八卦转为“二进制”的过程。 【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>使用…

Java进阶-泛型深入理解

概述 泛型是JDK5中引入的新特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查格式&#xff1a;<数据类型>&#xff1b;泛型只支持引用数据类型集合体系的全部接口和实现类都支持泛型的使用 集合详解→http://t.csdnimg.cn/R5zQ5 自定义泛型类 …