一. 为什么要引入状态机模式?

  1. 系统状态的变化引起实际行为的改变,因此我们需要在系统的主任务中判断他们处于哪一个状态,使用if-else if-else或者switch-case分支结构可以很好的解决。但是如果在某个每个状态在不同场景都有多个分支、并且需要频繁切换状态且状态繁多的系统中,如果仍然使用if-else if-else或者switch-case分支结构,会降低代码的可阅读性以及可维护性。
  2. 引入状态机模式,即是把所有的状态分隔为一层,将每个状态下遇到实际场景的行为分隔为一层,并将所有状态列出到一个表中,当需要增加替换删除某个状态时,直接修改状态表即可。
  3. 当系统遇到事件需要切换状态时,将事件转换为查表序号,然后直接进行查表得到切换后的状态即可,这样一来可以去除大量if-else if-else或者switch-case分支结构。虽然在查找状态的方法上分支模式的switch case和状态机模式的查表法在一定情况下效率是相近的(需要将外部事件进行转换才能得出状态的情况),但是在代码可阅读性以及可维护性上,分支模式是比不上状态机模式的。综上可知引入状态机模式一定程度上解决了代码可读性差和维护性差的问题,如图所示,在阅读和维护代码时的差别。

二. 状态机模式的实现

  1. 将系统切换状态的过程定义如下:原状态遇到某个事件,需要转换成现状态,现状态根据系统遇到的场景,选择合适的行为,即原状态->事件->转换->现状态->场景->行为。因此定义如下数据结构:
/*状态结构体*/
typedef struct _state
{void (*State_Prepare)(void);   //转换过程void (*State_Process)(void);  //状态处理void (*Behavior_Process)(void); //执行行为
}State_t;
typedef void(*Behavior_Table_pf)(void); //行为列表/*有限状态机*/
typedef struct _fsm
{unsigned char (*State_Change)(State_t *L_Sta,State_t *C_Sta); //判断状态是否改变State_t *Last_State;                   //上一状态State_t *Current_State;                   //当前状态State_t (*State_Table)[State_Column]; //状态驱动表,根据实际情况定义,此时表示状态驱动表是n行State_Column列
}FSM_t;
  1. 当建立一个状态机时,如底盘状态机时,进行如下初始化操作
FSM_t Chassis_Fsm;   //底盘状态机
/*状态驱动表这个根据实际情况定义,此时状态个数为State_Line*State_Column */
State_t            Chassis_State_Table[State_Line][State_Column];
/*行为驱动表这个根据实际情况定义,此时行为个数为Behavior_Num*/
Behavior_Table_pf  Chassis_Behavior_Table[Behavior_Num];/*初始化过程*//**定义并实现State_Line*State_Column个状态,并用他们初始*化状态驱动表Chassis_State_Table。*定义并实现Behavior_Num个行为,并用他们初始化行为驱动表*Chassis_Behavior_Table。*///将底盘状态机的状态驱动表指针指向Chassis_State_TableChassis_FSM.State_Table = Chassis_State_Table;
  1. 初始化完成后,将其送入状态机处理函数
/*此时参数s1和s2就是查表序号或外部事件,要根据实际情况定义函数参数*/
void FSM_Deal(FSM_t *fsm, unsigned char s1, unsigned char s2)
{/*误操作判断*/if(s1 <= 0 || s1 > State_Line || s2 <= 0 || s2 > State_Column){return;}/*状态指向*/fsm->Current_State = &fsm->State_Table[s1-1][s2-1];/*状态变化*/if( fsm->State_Change(fsm->Last_State,fsm->Current_State) == 1){fsm->Current_State->State_Prepare();}/*保留上次状态*/fsm->Last_State = fsm->Current_State;/*执行状态*/fsm->Current_State->State_Process();/*执行实际行为*/fsm->Current_State->Behavior_Process();
}
  1. 状态机处理函数中,有两个重要步骤,执行状态和执行实际行为,下面举一个例子展示这两个步骤
/*假设系统跳入了底盘独立运动状态*/
static void Chassis_Indepen_State(void)
{/* 对实际场景进行分析,得出行为驱动表索引值 */unsigned char bev_index = Scene_Analyse(&Chassis_FSM.Current_State);Chassis_FSM.Current_State->Behavior_Process = Chassis_Behavior_Table[bev_index];
}/*此时已根据实际场景,找到了该模式下的具体行为*/
/*假设跳到了扭腰行为*/
static void Chassis_Wiggle_bhv(void)
{//一套流程后,最终执行此函数
}

以上是我对状态机模式的一点理解,不足之处请在评论区指出。

参考资料:《C嵌入式编程设计模式》
https://bbs.huaweicloud.com/blogs/113179
https://www.zhihu.com/column/c_1136684995157577728

浅谈设计模式之状态机模式相关推荐

  1. 浅谈设计模式01-策略模式

    2019独角兽企业重金招聘Python工程师标准>>> 一. 定义 最近开始研读Head First设计模式,这本书给人的感觉耳目一新,不容易犯困啊.今天和大家分享一下策略模式. 1 ...

  2. 浅谈设计模式之五——Adapter模式

    这一节开始谈谈结构型模式.结构型模式包括:**适配器.桥接.组成.装饰.外观.享元.代理模式**7种设计模式.这一节说一下适配器模式,适配器模式可以分为类适配器和对象适配器,类适配器其实就是多继承,一 ...

  3. 浅谈Mediator仲裁者模式

    一.前言 Mediator模式又称为仲裁者模式或中介者模式,所起的作用就是仲裁和中介,帮助其它类之间进行交流.在仲裁者模式之中,我们要明确两个概念,那就是仲裁者(Mediator)和组员(Collea ...

  4. 浅谈企业中台商业模式及建设思路

    浅谈企业中台商业模式及建设思路 文章目录 浅谈企业中台商业模式及建设思路 前言 企业中台的定义和能力 企业中台的商业故事 企业中台的商业模式 构建企业中台时不同的企业初衷 企业中台的价值主张 企业中台 ...

  5. 【大话设计模式】——浅谈设计模式基础

    初学设计模式给我最大的感受是:人类真是伟大啊!单单是设计模式的基础课程就让我感受到了强烈的生活气息. 个人感觉<大话设计模式>这本书写的真好.让貌似非常晦涩难懂的设计模式变的生活化.趣味化 ...

  6. 状态机设计模式_设计模式-代理/状态机模式

    代理模式 是使率非常高的模式: 为其它对象提供一种代理以控制这个对象的访问.该模式也称为委托模式,在使用的时候代理模式可以为我们提供非常好的访问控制. 如下代码 interface IGamePlay ...

  7. 浅谈设计模式在iOS开发实战项目中的应用

    在我们日常的开发中设计模式伴随着项目的各个模块,巧妙地使用设计模式可以让我们写出更高效,简洁,优美的代码.可是因为对于设计模式的不熟悉,很多高效的设计模式并没有被很好地使用起来,而最近也正好在revi ...

  8. .NET简谈设计模式之(策略模式)

    策略模式在我们日常开发中经常被用到,这篇文章不是策略模式的深入讨论和学术研究,只是让初学者能有个基本的了解. 什么叫策略:1. 可以实现目标的方案集合:2. 根据形势发展而制定的行动方针和斗争方法:3 ...

  9. C#框架设计之浅谈SOA与钝化模式

    一. 什么是SOA SOA即为Service-Oriented Architecture缩写,翻译过来也就是面向服务的软件架构.通过将软件功能或者是业务流程进行服务化发布,从而达到一种面向于契约和服务 ...

最新文章

  1. 【Go】Go基础(九):接口(Interfaces)与反射(reflection)
  2. java 过滤器 中文_Java web整站中文过滤器实现
  3. 大数据工具篇之flume1.4-安装部署指南
  4. java高可用grpc_GRPC java 分布式调用链跟踪实践
  5. 索引-python编程技术-第二版
  6. 全局光照技术解析Global Illumination Explained
  7. Linux下解决高并发socket最大连接数限制,tcp默认1024个连接
  8. android 布局属性
  9. 一个月被曝五次数据泄露,ElasticSearch还行不行?
  10. downie是什么软件?如何在Mac中下载视频?
  11. 二级c语言考试怎么调试程序,计算机二级C语言上机考试操作步骤及流程和注意事项...
  12. 朋友圈那个随便辞职的年轻人,后来活成了什么样?
  13. dedecms织梦后台模板layui框架
  14. 推荐 :教你用神经网络求解高级数学方程!
  15. Android Gatekeeper梳理
  16. 【转】翻译中的黄金词组
  17. html页面高度和宽度,html和body元素的高度和宽度
  18. 内部排序(五)快速排序(上)- 概述与选择枢轴
  19. echarts 绘制省份地图 [ 把不同省份的市合并在一起 ]
  20. 南邮 OJ 1055 叙拉古猜想

热门文章

  1. 使用了的五年笔记本只是因为一个系统?就秒杀了阿里云服务器?
  2. 元宇宙与法律的梦幻联动 | Footprint Analytics
  3. WIN10系统禁用shift键更换输入法
  4. 品牌商家如何开通小红书蒲公英,注意事项
  5. Linux 如何查看.deb文件详细信息版本号包名
  6. 微信小程序实现单元格编辑功能,并支持计算合计
  7. NewStarCTF 公开赛赛道 第一周Web题目
  8. 手机 直面屏幕,2.5弧度屏,3D曲面屏
  9. 基于1DCNN(一维卷积神经网络)的机械振动故障诊断
  10. kaggle 旧金山犯罪案件分类预测