带你玩转状态机(论点:概念、相关图示、示例代码、适用场景、相关文档)

news2024/9/22 17:28:45

概念

        状态机(State Machine)是一种用于描述系统在不同状态下的行为及状态之间转换的数学模型。状态机主要由三个部分组成:状态(State)、事件(Event)和转换(Transition)。

  1. 状态(State):状态表示系统在特定时刻的条件或情况。一个状态机可以有多个状态,但在任意时刻,系统只能处于一个状态。
  2. 事件(Event):事件是导致状态之间转换的触发器。事件可以是外部输入,也可以是系统内部发生的事情。当事件发生时,系统可能会从当前状态转换到另一个状态。
  3. 转换(Transition):转换表示系统从一个状态到另一个状态的过程。转换通常会有一些条件或动作与之关联。条件表示在满足特定条件时才会发生状态转换,而动作表示在状态转换过程中执行的操作。

相关资料👉:有限状态机 - 维基百科,自由的百科全书 (wikipedia.org)

相关图示

        如下图所示,整个状态机包含5个节点,每个节点都有自己对应的逻辑,每个节点都可能执行多次
在这里插入图片描述

示例代码

       下面代码为上面图片的参考demo代码

//状态枚举
enum StateEnum {
	
	//定义开始节点以及结束节点,便于状态流转控制
    Start("doProcessA", new DoProcessA()),
    ProcessB("doProcessB", new DoProcessB()),
    ProcessC("doProcessC", new DoProcessC()),
    ProcessD("doProcessD", new DoProcessD()),
    End("", null);


    private String stateClassName;
    private State state;

    StateEnum(String stateClassName, State doProcessAClass) {
        this.stateClassName = stateClassName;
        this.state = doProcessAClass;
    }


    public String getStateClassName() {
        return this.stateClassName;
    }

    public void setStateClassName(final String stateClassName) {
        this.stateClassName = stateClassName;
    }

    public State getState() {
        return this.state;
    }

    public void setState(final State state) {
        this.state = state;
    }
}

//状态信息上下文
class StateContext {

    private List<String> processList;

    private static Map<String, State> statesMap = new ConcurrentHashMap<>();

    /**
     * 创建上下文
     * @return
     */
    public static StateContext createStateContext() {
        StateContext stateContext = new StateContext();
        stateContext.setProcessList(new ArrayList<>());
        return stateContext;
    }

    /**
     * 获取具体状态执行器
     * @param name
     * @return
     */
    public static State getStateByName(StateEnum name) {
        if (statesMap.size() == 0) {
            for (StateEnum value : StateEnum.values()) {
                if (!StateEnum.End.equals(value)){
                    statesMap.put(value.getStateClassName(), value.getState());
                }
            }
        }

        if (StateEnum.End.equals(name)) {
            return null;
        } else {
            return statesMap.get(name.getStateClassName());
        }
    }


    public List<String> getProcessList() {
        return this.processList;
    }

    public void setProcessList(final List<String> processList) {
        this.processList = processList;
    }
}


//抽象状态节点接口
interface State {
    void doProcess(StateContext stateContext);

    StateEnum nextState(StateContext stateContext);
}


//具体状态实现节点DoProcessA、DoProcessB、DoProcessC、DoProcessD
class DoProcessA implements State{
    @Override
    public void doProcess(StateContext stateContext) {
        System.out.println("processing A...");
        List<String> processList = stateContext.getProcessList();
        processList.add("process a");
        System.out.println("current processList:" + processList);
    }

    @Override
    public StateEnum nextState(StateContext stateContext) {
        return StateEnum.ProcessB;
    }
}


class DoProcessB implements State{
    @Override
    public void doProcess(StateContext stateContext) {
        System.out.println("processing B...");
        List<String> processList = stateContext.getProcessList();
        processList.add("process b");
        System.out.println("current processList:" + processList);
    }

    @Override
    public StateEnum nextState(StateContext stateContext) {
        //处理分支分叉
        if (null != stateContext.getProcessList() && stateContext.getProcessList().size() <= 3){
            return StateEnum.ProcessD;
        }
        return StateEnum.ProcessC;
    }
}

class DoProcessC implements State{
    @Override
    public void doProcess(StateContext stateContext) {
        System.out.println("processing C...");
        List<String> processList = stateContext.getProcessList();
        processList.add("process c");
        System.out.println("current processList:" + processList);
    }

    @Override
    public StateEnum nextState(StateContext stateContext) {
        return StateEnum.End;
    }
}

class DoProcessD implements State{
    @Override
    public void doProcess(StateContext stateContext) {
        System.out.println("processing D...");
        List<String> processList = stateContext.getProcessList();
        processList.add("process d");
        System.out.println("current processList:" + processList);
    }

    @Override
    public StateEnum nextState(StateContext stateContext) {
        return StateEnum.ProcessB;
    }
}

//测试demo
public class StateTest {
    public static void main(String[] args) {
        StateContext stateContext = StateContext.createStateContext();
        //定义开始节点
        StateEnum stateEnum = StateEnum.Start;
        State state = StateContext.getStateByName(stateEnum);

        do {
            //处理业务
            state.doProcess(stateContext);
            //设置下一个状态节点
            StateEnum nextStateEnum = state.nextState(stateContext);
            state = StateContext.getStateByName(nextStateEnum);
            //节点执行到结束节点后,状态机停止运行
        }while (!StateEnum.End.equals(stateEnum) && null != state);

        System.out.println("process end");
    }
}


运行结果
在这里插入图片描述

状态机适用场景

        状态机在处理具有复杂状态转换逻辑的场景时非常有用。以下是一些适用状态机的典型场景:

  1. 游戏开发:在游戏中,角色和对象可能有多种状态,如站立、移动、攻击等。使用状态机可以轻松地管理这些状态之间的转换和相关行为。
  2. 工作流引擎:工作流引擎需要处理业务流程中的多个步骤和状态,状态机可以帮助管理这些步骤之间的转换。
  3. 通信协议:在通信协议中,连接可能有多个状态,如建立、断开、重新连接等。状态机可以帮助实现协议的状态管理。
  4. 用户界面:在用户界面中,控件可能有多个状态,如激活、禁用、聚焦等。状态机可以使界面状态管理更加简洁和清晰。
  5. 自动售货机:自动售货机需要处理不同状态下的用户输入,如投币、选择商品、退币等。状态机可以有效地管理这些状态及其之间的转换。
  6. 有限状态自动机(Finite State Automata):在计算机科学中,有限状态自动机是一种理论模型,用于表示和分析具有有限状态集的离散时间系统。它在正则表达式、词法分析器、解析器等领域中有广泛应用。

        状态机适用于那些具有多个状态及状态之间存在复杂转换关系的场景。通过使用状态机,可以将复杂的逻辑分解为多个简单的状态,使代码更加易于理解和维护。

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

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

相关文章

Vue2-黑马(九)

0目录&#xff1a; &#xff08;1&#xff09;router-动态菜单 &#xff08;2&#xff09;vuex-入门 &#xff08;3&#xff09;vuex-mapState &#xff08;1&#xff09;router-动态菜单 我们点击按钮跳转到主页面&#xff0c;主页在制作动态菜单&#xff0c;路由的跳转方…

【PWN】刷题——CTFHub之 简单的 ret2text

萌新第一阶段自然是了解做题的套路、流程&#xff0c;简单题要多做滴 目录 前言 一、checksec查看 二、IDA反汇编 三、exp编写 前言 经典的ret2text流程 一、checksec查看 64位程序&#xff0c;什么保护都没有&#xff0c;No canary found——可以栈溢出控制返回 二、IDA反汇…

SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁

文章目录 1、步骤2、具体过程1、引入pom依赖2、修改配置文件3、单元测试4、测试结果 3、redis运行情况4、项目中实际应用5、加锁解决缓存击穿问题代码一&#xff08;存在问题&#xff09;代码二&#xff08;问题解决&#xff09; 6、新问题7、分布式锁 1、步骤 前提条件&#…

FFmpeg 编译静态库

1. 使用工具 1.1 FFmpeg 官网: 1.2 FFmpeg macOS 官方安装教程: 1.3 Homebreaw 安装网站: 2. Homebreaw 介绍 2.1 简称 brew&#xff0c;在 Mac 平台终端上管理软件包&#xff0c;安装&#xff0c;更新&#xff0c;卸载等软件 2.2 安装 brew&#xff0c;终端执行指令(内部安装…

HTTP协议详解(一)

目录 1.什么是HTTP协议? 2.HTTP的协议格式 使用fiddler抓包工具 理解代理 查看请求内容 3.HTTP请求(Request) 认识URL URL encode 认识method GET方法 POST方法 经典面试题:POST和GET之间的典型区别 其它方法 认识请求 "报头" (header) Host Conte…

Elasticsearch:为日志分析设置安全的 Elasticsearch 管道

在我之前的许多文章中&#xff0c;我已经详细地描述了如何配置如下的管道&#xff1a; 如果你想了解更多&#xff0c;请详细阅读文章&#xff1a; Logstash&#xff1a;Logstash 入门教程 &#xff08;二&#xff09; Elastic&#xff1a;运用 Docker 安装 Elastic Stack 并采…

企业在实施采购管理时需要注意哪些问题?

采购管理是指企业为了获得所需的物资和服务等&#xff0c;通过筛选供应商、谈判合同、执行采购计划等一系列过程来实现目标的管理活动。在实施过程中&#xff0c;采购管理需要注意以下几个问题&#xff1a; 1、采购策略的选择 采购策略的选择是采购管理中非常关键的环节。不同…

分享5款win10小工具,让办公学习井井有条

好用的小工具能让办公学习变得更简单便捷&#xff0c;这里推荐几款实用的Win10小工具。 桌面小工具——Win10 Widgets Win10 Widgets是一款实用的桌面小工具软件&#xff0c;可以让你在桌面上显示各种系统信息。你可以使用Win10 Widgets来查看电源、硬盘、CPU、内存、网络、时…

数据结构_第十三关(1):简单排序算法

【本关目标】 排序的概念常见排序的算法思想和实现排序算法的复杂度以及稳定性分析 目录 【本关目标】 1.排序的概念 2.常见排序的算法思想和实现&#xff08;代码默认都是从小到大排序&#xff09; 2.1插入排序 1&#xff09;直接插入排序 2&#xff09;希尔排序 2.2选…

Java 死锁的原理、检测和解决死锁

什么是死锁 两个或者多个线程互相持有对方所需要的资源&#xff08;锁&#xff09;&#xff0c;都在等待对方执行完毕才能继续往下执行的时候,就称为发生了死锁&#xff0c;结果就是两个进程都陷入了无限的等待中。 一般是有多个锁对象的情况下并且获得锁顺序不一致造成的。 …

微服务+springcloud+springcloud alibaba学习笔记【Spring Cloud Gateway服务网关】(7/9)

Spring Cloud Gateway服务网关 7/9 1、GateWay概述2、GateWay的特性:3、GateWay与zuul的区别:4、zuul1.x的模型:5、什么是webflux:6、GateWay三大概念:6.1,路由:6.2,断言:6.3,过滤: 7、GateWay的工作原理:8、使用GateWay:8.1,建module8.2,修改pom文件8.3,写配置文件8.4,主启动类…

微服务学习——微服务框架

Nacos配置管理 统一配置管理 配置更改热更新 将配置交给Nacos管理的步骤&#xff1a; 在Nacos中添加配置文件在微服务中引入nacos的config依赖在微服务中添加bootstrap.yml&#xff0c;配置nacos地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去nacos读取哪个…

Java:JDK对IPv4和IPv6处理介绍

以下以JDK8为例说明对IPv4和IPv6是如何处理的。 一、常用代码 一般情况下&#xff0c;使用如下代码可以获取到域名/主机名对应的多个IP&#xff0c;其中部分是IPv4的&#xff0c;部分是IPv6的&#xff1a; try {InetAddress[] addrs InetAddress.getAllByName(host);for (I…

Quartz框架详解分析

文章目录 1 Quartz框架1.1 入门demo1.2 Job 讲解1.2.1 Job简介1.2.2 Job 并发1.2.3 Job 异常1.2.4 Job 中断 1.3 Trigger 触发器1.3.1 SimpleTrigger1.3.2 CornTrigger 1.4 Listener监听器1.5 Jdbc store1.5.1 简介1.5.2 添加pom依赖1.5.3 建表SQL1.5.4 配置文件quartz.propert…

23-HTTP协议

目录 1.HTTP是什么&#xff1f; 2.HTTP工作过程 3.HTTP协议格式 3.1.抓包工具使用 eg&#xff1a;抓取"必应"的包 PS&#xff1a;HTTP不同版本号之间的区别 3.2.抓包工具原理 3.3.抓包结果分析 ①HTTP 请求&#xff1a; ②HTTP 响应&#xff1a; 3.4.协议…

ArduPilot Kakute F7 AIO DIYF450 without GPS配置

ArduPilot Kakute F7 AIO DIYF450 without GPS配置 1. 源由2. 配置2.1 Kakute F7 AIO相关配置2.1.1 串口规划2.1.2 电传配置2.1.3 GPS配置2.1.4 CRSF接收机配置2.1.5 Compass配置2.1.6 电机配置2.1.7 TX12 遥控器配置 3. 实测效果4. 参考资料 1. 源由 鉴于GPS模块信号质量未达…

3DEXPERIENCE云可以为PLM带来什么?

在消费者领域&#xff0c;云的优势已显而易见&#xff0c;用一个词就可以概括&#xff1a;便利&#xff0c;3DEXPERIENCE云存储服务的用户可以从任何位置在任何设备上访问其数据&#xff0c;只要能够连接到互联网就行了。在一台设备 上所做的更改会立即反映在另一台设备上。 同…

提升10倍写作效率,这5个写作工具,文笔不好的人别错过

记得刚出来上班的时候&#xff0c;我的写作效率很低&#xff0c;经常没有思路&#xff0c;也找不到选题。甚至一两个小时过去了&#xff0c;仍然不知道如何动笔&#xff0c;经常写了删&#xff0c;删了又写。工欲善其事&#xff0c;必先利其器。在写作过程中&#xff0c;需要一…

【数据分析之道-NumPy(五)】numpy迭代数组

文章目录 专栏导读1、前言2、使用python循环语句3、使用nditer函数3.1迭代一维数组3.2迭代二维数组3.3迭代指定顺序的数组3.4迭代时修改数组中的元素 4、使用flat属性5、使用ndenumerate函数6、使用布尔索引总结 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN Python…

IO多路复用—多线程网络并发通信 select poll epoll

1.IO 多路转接 (复用) ​ IO 多路转接也称为 IO 多路复用&#xff0c;它是一种网络通信的手段&#xff08;机制&#xff09;&#xff0c;通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的&#xff0c;一旦检测到有文件描述符就绪&#xff08; 可以读数据或者可以写…