状态机

注意
本文最后更新于 2024-05-06,文中内容可能已过时。

状态机

维基百科:有限状态机 - 维基百科,自由的百科全书

参考博客:什么是状态机?一篇文章就够了 - 掘金

状态机一般指有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机(英语:finite-state automaton,缩写:FSA),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型

状态机是一种抽象的数学模型

状态机中有几个术语:state(状态)transition(转移)action(动作)transition condition(转移条件)

  • state(状态) :将一个系统离散化,可以得到很多种状态,当然这些状态是有限的。例如:门禁闸机可以划分为开启状态、关闭状态;电扇可以划分为关、一档、二档、三档等状态。

  • transition(转移) :一个状态因为某些事件比如(接收一个输入)执行了某些动作到达了另外一个状态的过程就是一个 transition(转移)。定义 transition(转移) 就是在定义状态机的转移流程。

  • transition condition(转移条件) :也叫做 Event(事件),在某一状态下,只有达到了 transition condition(转移条件),才会按照状态机的转移流程转移到下一状态,并执行相应的动作。

  • action(动作):在状态机的运转过程中会有很多种动作。如:进入动作 (entry action)[在进入状态时进行]、退出动作 (exit action)[在退出状态时进行]、转移动作[在进行特定转移时进行]。在实际编程的时候,一个 Action 一般就对应一个函数。

每一个状态机,都可以画出状态转移图,比如

有限状态机可以被分为不同的类型,主要可以被分为:acceptors(接收器)transducers(转换器) 两大类

  • acceptors(接收器) 是指产生一个二值的输出,指示接收的输入是否能被接受。acceptors(接收器) 的每一种状态都是接受或不接受的。

  • transducers(转换器) 是根据当前的状态和 (或) 给定的输入产生输出,输出的同时可能也伴随着状态的转移 (不是必须)。在一些事件驱动型应用和计算语言学 (computational linguistics) 领域应用普遍。transducers(转换器) 型有限状态机可以分为两种子类型,moore machine(摩尔型有限状态机) 和mealy machine(米利型有限状态机) ,其中:

    • 若输出只和状态有关而与输入无关,则称为 moore 状态机
    • 输出不仅和状态有关而且和输入有关系,则称为 mealy 状态机

这里我们就不仔细区分了。


在实际的开发过程中,state 和 transition 和 transition condition 是静态的,是固定的,是我们在开发之前就需要明确定义好的内容,是抽象模型本身,而何时触发 transition condition 或者说 Event,以及被开始 transition 的时候的各种动作,是状态机使用者需要实现的,我们实现一个状态机之后,需要留出这两种钩子,让状态机的用户也就是开发者可以根据自己的需要来自定义这些方法,使用状态机,具体的理解请看小节通过JavaScript实现一个状态机


现在的很多事件驱动的前端框架,比如 React,本质上就是把网页应用当成了一个状态机,我们在学习这些前端框架的时候,用状态机的视角去看,会清晰很多,在使用这些前端框架的时候,需要在脑海中清晰地区分这四个概念,这样我们写出来的代码才是逻辑清晰的。

其实除了前端领域,后端领域的很多东西也都可以看成是状态机,比如线程的生命周期,也都可以画出状态转化图。

其实归根结底,状态机表示的是在有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。状态机是一种抽象的数学模型。

通过 JavaScript 实现一个状态机

参考代码:GitHub - jakesgordon/javascript-state-machine: A javascript finite state machine library

通过代码实现这样一个状态机

下载下来 JavaScript 文件:fsmJS

然后创建 HTML 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src='state-machine.js'></script>
<script>
    var fsm = new StateMachine({
        init: 'solid',
        transitions: [
            {name: 'melt', from: 'solid', to: 'liquid'},
            {name: 'freeze', from: 'liquid', to: 'solid'},
            {name: 'vaporize', from: 'liquid', to: 'gas'},
            {name: 'condense', from: 'gas', to: 'liquid'}
        ],
        methods: {
            onMelt: function () {
                console.log('I melted')
            },
            onFreeze: function () {
                console.log('I froze')
            },
            onVaporize: function () {
                console.log('I vaporized')
            },
            onCondense: function () {
                console.log('I condensed')
            }
        }

    
    });
    // 输出 I melted
    fsm.melt();

</script>
<body>

</body>
</html>

通过以下方法,我们可以转换状态机的状态,对以下方法的调用,就是 Event 或者说 transition condition,调用这些方法之后,实现的状态的转换,就是 transition

  • fsm.melt()
  • fsm.freeze()
  • fsm.vaporize()
  • fsm.condense()

以下回调函数会在进行指定状态的时候被调用,可以看作是 action

  • onMelt()
  • onFreeze()
  • onVaporize()
  • onCondense()
0%