转自:深入浅出理解有限状态机 - 知乎

有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。在计算机科学中,有限状态机被广泛用于建模应用行为、硬件电路系统设计、软件工程,编译器、网络协议、和计算与语言的研究。比如下图非常有名的TCP协议状态机。

其实我们在编程时实现相关业务逻辑时经常需要处理各种事件和状态切换,写各种switch/case 和if/else ,所以我们其实可能一直都在跟有限状态机打交道,只是可能没有意识到。在处理一些业务逻辑比较复杂的需求时,可以先看看是否适合用一个有限状态机来描述,如果可以把业务模型抽象成一个有限状态机,那么代码就会逻辑特别清晰,结构特别规整。
下面我们就来聊聊所谓的状态机,以及它如何在代码中实现。
1、状态机的要素
状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:
①现态:是指当前所处的状态。
②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
我们可以用状态表了表示整个过程,如下图所示。

状态表
这里需要注意的两个问题:
1、避免把某个“程序动作”当作是一种“状态”来处理。那么如何区分“动作”和“状态”?“动作”是不稳定的,即使没有条件的触发,“动作”一旦执行完毕就结束了;而“状态”是相对稳定的,如果没有外部条件的触发,一个状态会一直持续下去。
2、状态划分时漏掉一些状态,导致跳转逻辑不完整。
所以维护上述一张状态表就非常必要,而且有意义了。从表中可以直观看出那些状态直接存在跳转路径,那些状态直接不存在。如果不存在,就把对应的单元格置灰。 每次写代码之前先把表格填写好,并且对置灰的部分重点review,看看是否有“漏态”,然后才是写代码。QA拿到这张表格之后,写测试用例也是手到擒来。
2、状态机在object-C的代码实现。
我在开发百度地图导航过程页以及百度CarLife的反控手机识别中都用到了有些状态机编程,下面我结合个人的经验,给大家分享一个iOS程序中实现有限状态机的写法。
先回顾一下上面那个状态表,其中状态变迁时执行的动作,可能是由一系列的元动作组成,并且通常都是跟现态和次态强相关的,所以,我把状态表做一个改进,如下所示:

其中:FSM_FUN(stateA,stateB) 就表示,从状态stateA跳转到stateB时要执行的所有元动作的有序集。
1、准备工作,状态定义和事件定义

宏定义
这里没有啥特殊的,主要是借助宏定义,比较巧妙的实现枚举值到字符串的转换,比如枚举值stateA,能自动生成字符串@“stateA”,用于后面的状态函数名拼接。这是一个通用的枚举值自动转字符串的解决方案,参考的链接( http://stackoverflow.com/a/202511)
2、Model类定义
iOS开发都会采用MVC架构或者相关变种,但是状态的维护都会实现在Model中。这里定义了一个简单的TestModel,它有一个成员变量state,保存着当前的状态。

Model定义
3、实现Model类的一个category,
里面主要定义和实现了状态跳转时要执行的一些动作。

4、重新Model的setState方法,使得在设置状态时能自动去执行状态跳转时需要执行的动作。

5、处理事件输入,实现状态跳转逻辑。
这里有两种写法,一种是在状态中判断事件:

状态中判断事件
一种是事件中判断状态:

事件中判断状态
思考与讨论:
状态跳转逻辑的两种写法,实现的功能和效果完全相同,孰优孰劣,欢迎留言探讨。
本人观点:一般业务场景来说,状态的数量是确定的切数目较少,不同状态下需要处理的事件也不一样。而触发的事件数量则比较多,采用上面第二种方式在事件中判断状态也有利于把里面一层的switch/case剥离出来当成单独的函数,做一些代码模块结构的优化,故推荐使用第二种方式,事件中判断状态
优化后的状态变化函数代码,如下图。

优化后
欢迎探讨
本文主要介绍了一下什么是有限状态机,然后通过一个具体的代码示例介绍了一些本人在状态机编程上的经验和理解,欢迎各位进行交流指正。
谢谢大家的宝贵时间。
微信公众号:云峰小罗,分享 编程.生活.段子

http://weixin.qq.com/r/bkXr8zjEkmXtrXyQ9xB8 (二维码自动识别)

【转】深入浅出理解有限状态机相关推荐

  1. 深入浅出理解有限状态机

    有限状态机 有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件.在计算机科学中,有限状态机被广泛用于建模应用行为.硬件电路 ...

  2. 今晚8点直播 | 深入浅出理解A3C强化学习

    强化学习是一种比较传统的人工智能手段,在近年来随着深度学习的发展,强化学习和深度学习逐渐结合在了一起.这种结合使得很多原来无法想象的工作有了可能,最令我们瞩目的莫过于AlphaGo战胜李世石,以及Op ...

  3. 今晚直播 | 深入浅出理解A3C强化学习

    强化学习是一种比较传统的人工智能手段,在近年来随着深度学习的发展,强化学习和深度学习逐渐结合在了一起.这种结合使得很多原来无法想象的工作有了可能,最令我们瞩目的莫过于AlphaGo战胜李世石,以及Op ...

  4. 公开课报名 | 深入浅出理解A3C强化学习

    强化学习是一种比较传统的人工智能手段,在近年来随着深度学习的发展,强化学习和深度学习逐渐结合在了一起.这种结合使得很多原来无法想象的工作有了可能,最令我们瞩目的莫过于AlphaGo战胜李世石,以及Op ...

  5. 深入浅出理解c++虚函数

    深入浅出理解c++虚函数 记得几个月前看过C++虚函数的问题,当时其实就看懂了,最近笔试中遇到了虚函数竟然不太确定,所以还是理解的不深刻,所以想通过这篇文章来巩固下. 装逼一刻: 最近,本人思想发生了 ...

  6. 计算机操作系统开启审计功能,深入浅出理解操作系统安全

    原标题:深入浅出理解操作系统安全 引言 操作系统安全在计算机信息系统的整体安全性中具有至关重要的作用,没有操作系统提供的安全性,计算机业务系统的安全性是没有基础的. 什么是操作系统 操作系统(英语:o ...

  7. 深入浅出理解索引结构

    (一)深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonc ...

  8. 深入浅出强化学习_直播 | 深入浅出理解 A3C 强化学习

    强化学习是一种比较传统的人工智能手段,在近年来随着深度学习的发展,强化学习和深度学习逐渐结合在了一起. 这种结合使得很多原来无法想象的工作有了可能,最令我们瞩目的莫过于 AlphaGo 战胜李世石,以 ...

  9. 音视频开发(29)---深入浅出理解视频编码H264结构

    深入浅出理解视频编码H264结构 编码流程: 那么 H.264 其编解码流程是怎么样的呢?其实可以主要分为 5 部分: 帧间和帧内预测(Estimation).变换(Transform)和反变换.量化 ...

最新文章

  1. VS2012经常使用的快捷方式完成最全面
  2. 中国石材胶市场需求现状调研与前景预测分析报告2022版
  3. DVWA-暴力破解-对‘g0tmi1k’文章的学习笔记
  4. 华容道与数据结构 (续 3)
  5. JavaWeb项目框架
  6. 利用Python进行数据分析的学习笔记——chap12
  7. IDEA使用Git大全
  8. 项目沟通管理和项目干系人管理
  9. 深度学习(deep learning)发展史
  10. 【Linux】Ubuntu20网络频繁掉线解决
  11. 微信公众号的留言功能
  12. JDBC心得体会--总结
  13. Hexo速度优化及遇到的问题(gulp4、hexo-neat)
  14. c语言 快速筛质数,快速筛素数(埃式筛+线性筛+Miller_Rabin算法)
  15. Elegy written in a country church-yard
  16. php考试段位系统,中国武术段位临汾考区初级段位考试圆满结束
  17. XRD粉末样品的制备,你必需知道这2点
  18. Linux处理二进制文件工具
  19. C语言处理excel
  20. 【愚公系列】2022年09月 python人工智能-PyTorch环境配置及安装

热门文章

  1. C# Json转对象
  2. Lesson 028 —— python 模块
  3. 汇编软件的安装与实验一
  4. HttpContext
  5. [iOS] 建立与使用Framework
  6. jQuery之ajax的跨域获取数据
  7. 使用参数来防止SQL注入
  8. 关于增强(五)-Class Enhancement
  9. git merge用法_常用命令之git操作(进阶篇)
  10. 消息队列控制灯代码_代码实现RabbitMQ死信队列的创建