【转】深入浅出理解有限状态机

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

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

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

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

相关文章

2010读书计划

跟别人学着将今年想看的书发出来: 1.Implementing Lean Software Development --Mary and Tom Poppendieck 2.沉浮 3.Algorithm of the intelligent web --haralambos Marmanis 4.数据结构-严蔚敏 还有今年是比较重要的一年,加油。。。转载于:https://ww…

wince 环境变量

wince工程的环境变量在PBInitEnv.bat文件中存储,经测试,如果在下面增加了新的变量,在此文件中会出现

【转】vs平台工具集介绍,vc6~vs2019各IDE对应的工具集版本

转自:vs平台工具集介绍以及安装 - jack_Meng - 博客园 一、什么是平台工具集: 平台工具集其实是MSBuild其目录所在C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0。VS从2010之后开始支持使用之前的版本进行编译,可以在工程属性->常…

基于FPGA的前向纠错算法

目前,无线产品的广泛应用使无线音频和视频的高质量传输成为可能。蓝牙、无限局域网等无线传输设备比较复杂,成本较高,急需 开发一种简便的、仅用于流媒体的无线传输平台,将音频数据实时地发送到移动终端。由于音频数据的实时性&am…

wince编译时找不到atls.lib

NMAKE : fatal error U1073: dont know how to make C:\WINCE600\OSDesigns\x210\x210\Wince600\SMDKV210_ARMV4I\cesysgen\oak\lib\ARMV4I\retail\atls.lib 需要选择ATL

【转】Windows版本,OS内核版本,Windows SDK之间的关系

转自:Windows版本,OS内核版本,Windows SDK之间的关系 - 知乎 前言:我们经常会会被几个概念弄混淆,什么是Windows版本号,什么又是操作同内核版本,开发C的时候什么又是WindowsSDK,实际…

ADO.NET Entity Framework 使用中的经验总结

ADO.Net EF框架非常的灵活,好的习惯可以提高性能,而不好的习惯就会减少性能,为了提高性能简化开发,总结网络给出下面的经验。 1.如果要扩展实体类的功能,应该通过“部分类”(partial)实现 2.如果需要借助ObjectContext…

怎样在PropertySheet中添加按钮

1、用ClassWizard从CPropertySheet中派出出一个类CMyPropertySheet; 2、在CMyPropertySheet.h中添加一个成员变量CButton m_ButtonCopy;在资源文件resource.h中添加一个资源ID:#define IDC_BUTTON_COPY 0x2000,这个ID就是我们将要用到的Copy按钮的ID&#xff…

【转】30分钟学会UML类图

转自:30分钟学会UML类图 - 知乎 30分钟学会UML类图 肖继潮 UML图有很多种,但是并非必须掌握所有的UML图,才能完整系统分析和设计工作。一般说来,在UML图中,只要掌握类图、用例图、时序图的使用,就能完成大…

Microsoft SQL Server 2005数据库安装

Microsoft SQL Server 2005数据库,电脑里原有的mssql2000已经不适用了,到网上寻找SQL Server 2005简体中文开发版的下载地址,一开始下载了个学习版的express,可限制太多,还是决心安装开发版本的。到微软的官方网站寻找…

深入浅出 CPropertySheet

为了最大限度的发挥属性页的效用,首先让我们先从 CPropertySheet 继承一个新类,取名为 CMyPropSheet. 接着便可以进行下面的各种操作: 一、隐藏属性页默认按钮 隐藏掉Apply应用按钮: view source print?1.propsheet.m_psh.dwFlags | PSH_NOAPPLY…

【转】make makefile cmake qmake都是什么,有什么区别?

转自: 作者:知乎用户 链接:https://www.zhihu.com/question/27455963/answer/89770919 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 1.gcc是GNU Compiler Collection&#xf…

WinCE 字体平滑 ClearType

WinCE 5.0 字体效果糙,英文字体(Zurich)可以在代码里面设置ClearType,中文字体不行。 解决方法: [HKEY_LOCAL_MACHINE\System\GDI] "FontLinkMethods"dword:00000000 [HKEY_LOCAL_MACHINE\System\GDI\Cle…

用ASP.NET 2.0设计网络在线投票系统

一、系统功能设计和数据库设计 1、系统功能设计和数据库设计 1.1 系统功能设计 网络在线投票系统实现的功能比较简单,具体如下: ◎投票项目的管理; ◎添加投票的项目; ◎删除投票的项目; ◎对项目进行投票&#xff1…

Convert.Int32、(int)和int.Parse三者的区别

今天去面试,碰到这样一道题目,回来查了下答案~! Convert.ToInt32、(int)和int.Parse三者的区别: 前者适合将object类类型转换成int类型,如Convert.ToInt32(session["shuzi"]); (int)适合简单数据类型之间的转…

Wince6.0 cleartype

WinCE6.0下显示宋体毛刺很严重,影响显示效果,打开cleartype以后字体显示平滑,但是不知道为什么wince桌面上的中文字体显示乱码,而且自己的引用程序也变的很卡。 开始以为是字库的原因,后来添加了系统的组件以后一切正常…

【转】ubuntu16.04安装配置tftp服务

转自:ubuntu16.04安装配置tftp服务_carspiriter的博客-CSDN博客_ubuntu安装tftp 首先声明:tftp是client客户端,tftpd是server服务器端,d应该指的是daemon。如果你要从别人的tftp服务器端上传/下载东西,就要用到tftp&a…

如何编程得到数据库信息

获取数据库信息&#xff1a;public List<string> GetDatabase(string connectionString) {using (SqlDataAdapter sqlDataAdapter new SqlDataAdapter("SELECT Name FROM Master.sys.SysDatabases WHERE dbid > 4 ORDER BY Name ", connectionStrin…

【转】Dicom中的Image Orientation/Position的理解

转自&#xff1a;Dicom中的Image Orientation/Position的理解 - 知乎 在DICOM中&#xff0c;是通过Image Position和Image Orientation来描述当前的图像和人体坐标系的相对位置的。 打开DCM文件时&#xff0c;会发现下边的两个tag (0020,0032) DS ImagePosition(Patient) &q…

搭建TFS2008的过程及其注意事项

TFS服务端的安装 1、安装windows Server 2003 操作系统 2、打windows Server 2003 sp2 补丁 3、安装iis, 记得选上asp.net &#xff0c;不能选extend homepage 4、访问 Microsoft 网站上的 Windows Update&#xff0c;并安装“高优先级更新程序”组中的所有项 5、装上ms sql2…