讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

剧云
剧云

中文短剧剧本制作平台

Seko
Seko

AI短剧一键生成成片

Laper
Laper

剧本策划到成片协作

什么是状态机?有限状态机的实现

大强大大_8951

大强大大_8951

发布时间:2025-08-20 14:11:01

|

678人浏览过

|

来源于php中文网

原创

有限状态机常见实现方式有:基于枚举和switch/case语句,适合简单场景但难以维护;状态模式通过封装状态类提升扩展性但类数量增多;状态转换表以表格形式清晰表达转换规则但规模大时复杂;基于框架或库如Spring Statemachine可支持高级功能。选择方式需根据复杂度和需求权衡。

什么是状态机?有限状态机的实现

状态机,简单来说,就是一种描述对象在不同状态之间转换的数学模型。它定义了一组状态、事件以及状态转换的规则。有限状态机(FSM)则意味着状态的数量是有限的。

状态机在软件开发中用途广泛,例如控制游戏角色的行为、解析网络协议、管理用户界面等等。理解状态机,能让你更好地组织代码逻辑,提高程序的可维护性和可扩展性。

状态机的核心在于定义清晰的状态和状态转换。

有限状态机的常见实现方式有哪些?

实现有限状态机的方法有很多,常见的包括:

  1. 基于枚举和switch/case语句: 这是最简单直接的方式。使用枚举类型定义状态,然后使用switch/case语句根据当前状态和输入事件来决定下一个状态。

    enum State {
        IDLE,
        RUNNING,
        STOPPED
    }
    
    State currentState = State.IDLE;
    
    void processEvent(Event event) {
        switch (currentState) {
            case IDLE:
                if (event == Event.START) {
                    currentState = State.RUNNING;
                    // 执行进入RUNNING状态的动作
                    System.out.println("进入RUNNING状态");
                }
                break;
            case RUNNING:
                if (event == Event.STOP) {
                    currentState = State.STOPPED;
                    // 执行进入STOPPED状态的动作
                    System.out.println("进入STOPPED状态");
                } else if (event == Event.PAUSE) {
                    currentState = State.IDLE;
                    System.out.println("进入IDLE状态");
                }
                break;
            case STOPPED:
                if (event == Event.RESET) {
                    currentState = State.IDLE;
                    // 执行进入IDLE状态的动作
                    System.out.println("进入IDLE状态");
                }
                break;
        }
    }
    
    enum Event {
        START,
        STOP,
        RESET,
        PAUSE
    }
    
    public static void main(String[] args) {
        FiniteStateMachineExample fsm = new FiniteStateMachineExample();
        fsm.processEvent(Event.START);
        fsm.processEvent(Event.STOP);
        fsm.processEvent(Event.RESET);
    }

    这种方式的优点是简单易懂,但缺点是当状态数量增多时,switch/case语句会变得非常冗长,难以维护。

  2. 状态模式: 状态模式是一种设计模式,它将每个状态封装成一个独立的类,并定义一个上下文类来维护当前状态。当接收到事件时,上下文类将事件委托给当前状态对象处理。

    // 状态接口
    interface State {
        void handleEvent(Context context, Event event);
    }
    
    // 具体状态类
    class IdleState implements State {
        @Override
        public void handleEvent(Context context, Event event) {
            if (event == Event.START) {
                System.out.println("Idle -> Running");
                context.setState(new RunningState());
            }
        }
    }
    
    class RunningState implements State {
        @Override
        public void handleEvent(Context context, Event event) {
            if (event == Event.STOP) {
                System.out.println("Running -> Stopped");
                context.setState(new StoppedState());
            } else if (event == Event.PAUSE) {
                System.out.println("Running -> Idle");
                context.setState(new IdleState());
            }
        }
    }
    
    class StoppedState implements State {
        @Override
        public void handleEvent(Context context, Event event) {
            if (event == Event.RESET) {
                System.out.println("Stopped -> Idle");
                context.setState(new IdleState());
            }
        }
    }
    
    // 上下文类
    class Context {
        private State state;
    
        public Context() {
            this.state = new IdleState(); // 初始状态
        }
    
        public void setState(State state) {
            this.state = state;
        }
    
        public void processEvent(Event event) {
            this.state.handleEvent(this, event);
        }
    
        public State getState() {
            return state;
        }
    }
    
    enum Event {
        START,
        STOP,
        RESET,
        PAUSE
    }
    
    public class StatePatternExample {
        public static void main(String[] args) {
            Context context = new Context();
            context.processEvent(Event.START);
            context.processEvent(Event.STOP);
            context.processEvent(Event.RESET);
        }
    }

    状态模式的优点是结构清晰,易于扩展和维护。缺点是需要创建较多的类。

    Token Guard Model Switch
    Token Guard Model Switch

    监控token使用量和上下文负载以防止中断,当阈值超出时自动切换到备用模型。

    下载
  3. 状态转换表: 状态转换表是一种将状态转换规则以表格形式存储的数据结构。表格的每一行代表一个状态,每一列代表一个事件,表格中的单元格则表示在当前状态下接收到该事件后要转换到的下一个状态。

    import java.util.HashMap;
    import java.util.Map;
    
    enum State {
        IDLE,
        RUNNING,
        STOPPED
    }
    
    enum Event {
        START,
        STOP,
        RESET,
        PAUSE
    }
    
    public class StateTransitionTableExample {
    
        private State currentState;
        private Map<State, Map<Event, State>> transitionTable;
    
        public StateTransitionTableExample() {
            currentState = State.IDLE;
            transitionTable = new HashMap<>();
    
            // 初始化状态转换表
            Map<Event, State> idleTransitions = new HashMap<>();
            idleTransitions.put(Event.START, State.RUNNING);
            transitionTable.put(State.IDLE, idleTransitions);
    
            Map<Event, State> runningTransitions = new HashMap<>();
            runningTransitions.put(Event.STOP, State.STOPPED);
            runningTransitions.put(Event.PAUSE, State.IDLE);
            transitionTable.put(State.RUNNING, runningTransitions);
    
            Map<Event, State> stoppedTransitions = new HashMap<>();
            stoppedTransitions.put(Event.RESET, State.IDLE);
            transitionTable.put(State.STOPPED, stoppedTransitions);
        }
    
        public void processEvent(Event event) {
            Map<Event, State> transitions = transitionTable.get(currentState);
            if (transitions != null && transitions.containsKey(event)) {
                State nextState = transitions.get(event);
                System.out.println("状态从 " + currentState + " 转换到 " + nextState + ",事件:" + event);
                currentState = nextState;
            } else {
                System.out.println("无效的事件 " + event + " 在状态 " + currentState + " 下");
            }
        }
    
        public static void main(String[] args) {
            StateTransitionTableExample fsm = new StateTransitionTableExample();
            fsm.processEvent(Event.START);
            fsm.processEvent(Event.STOP);
            fsm.processEvent(Event.RESET);
            fsm.processEvent(Event.PAUSE); // 无效事件示例
        }
    }

    使用状态转换表可以清晰地表达状态转换逻辑,易于修改和扩展。但是,当状态和事件数量较多时,状态转换表会变得非常庞大。

  4. 基于框架或库: 许多编程语言和框架都提供了状态机库,例如Spring Statemachine (Java), 这些库通常提供了更高级的功能,例如状态持久化、事件队列、状态监听器等。使用这些库可以简化状态机的开发过程。

选择哪种实现方式取决于具体的应用场景。对于简单的状态机,基于枚举和switch/case语句可能就足够了。对于复杂的状态机,状态模式或状态转换表可能更合适。如果需要更高级的功能,可以考虑使用状态机库。

如何设计一个良好的状态机?

设计良好的状态机需要考虑以下几个方面:

  1. 明确状态和事件: 首先要明确定义状态机的所有状态和事件。状态应该能够清晰地描述对象的不同状态,事件应该能够触发状态之间的转换。
  2. 定义状态转换规则: 明确定义每个状态在接收到不同事件时应该转换到哪个状态。可以使用状态转换图或状态转换表来描述状态转换规则。
  3. 处理无效事件: 当状态机接收到无效事件时,应该进行适当的处理。例如,可以忽略该事件,或者抛出一个异常。
  4. 考虑状态的层次结构: 对于复杂的状态机,可以考虑使用状态的层次结构来简化设计。例如,可以将一些状态组合成一个父状态,父状态可以包含多个子状态。
  5. 进行充分的测试: 设计完成后,需要进行充分的测试,以确保状态机能够正确地处理各种事件,并达到预期的效果。

状态机在实际项目中的应用案例

状态机在各种软件系统中都有广泛的应用。以下是一些常见的例子:

  • 游戏开发: 游戏角色的行为控制,例如Idle、Walking、Running、Jumping、Attacking等状态之间的切换。
  • 网络协议: TCP协议的状态机,例如CLOSED、LISTEN、SYN_SENT、SYN_RECEIVED、ESTABLISHED等状态之间的转换。
  • 用户界面: 用户界面的状态管理,例如Loading、Displaying、Editing等状态之间的切换。
  • 工作流引擎: 业务流程的状态管理,例如Submitted、Approved、Rejected、Completed等状态之间的转换。
  • 机器人控制: 机器人行为的状态管理,例如Idle、Moving、Scanning、Charging等状态之间的转换。

状态机是一种强大的工具,可以帮助我们更好地组织和管理复杂的程序逻辑。通过合理的设计和实现,可以提高程序的可维护性和可扩展性。

热门AI工具

更多
讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2971

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

517

2026.01.26

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

1071

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

1457

2024.03.13

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2901

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

416

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

437

2026.01.06

C++ 数据结构与算法实现教程合集
C++ 数据结构与算法实现教程合集

以 C++ 为实现语言,系统讲解核心数据结构与算法,涵盖链表(单链表/双链表/环检测)、栈与队列(单调栈/优先队列)、二叉树(遍历/BST/AVL/红黑树)、哈希表(开地址法/链地址法)、图(邻接表/BFS/DFS/Dijkstra/拓扑排序)、常见排序算法(快排/归并/堆排/计数排序)的实现与复杂度分析,同时分享 LeetCode 刷题技巧、竞赛编程常用模板(二分/前缀和/滑动窗口/动态规划),帮助开发者夯实算法基础。

492

2026.05.09

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue.js 微实战--十天技能课堂
Vue.js 微实战--十天技能课堂

共18课时 | 1.7万人学习

mysql8主从复制原理底层详解
mysql8主从复制原理底层详解

共1课时 | 715人学习

Go-Zero goctl安装与使用手册
Go-Zero goctl安装与使用手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn