分享

设计模式之状态模式

 启云_9137 2022-05-27 发布于湖南

介绍:

状态模式是一种行为模式,它与有限状态机的概念紧密相关;其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移

文章图片1

有限状态机


作用:

将业务模型抽象成一个有限状态机,减少大量的switch-caseif-else的使用,使得代码逻辑清晰,结构规整;


类比:

智能手机的按键和开关会根据设备当前状态完成不同行为:

  • 当手机处于解锁状态时, 按下按键将执行各种功能。
  • 当手机处于锁定状态时, 按下任何按键都将解锁屏幕。
  • 当手机电量不足时, 按下任何按键都将显示充电页面。

以BLE链路层状态机为例:

文章图片2

BLE链路层状态机

#include <stdio.h>#include <assert.h>#include <stdbool.h>/*链路层状态*/typedef enum{ SCAN, STANDBY, ADV, CONN, INIT,}SM_STATE;/*触发事件*/typedef enum{ EVENT1, EVENT2, EVENT3, EVENT4, EVENT5, EVENT6, EVENT7, EVENT8, EVENT9,}SM_EVENT;/*回调*/typedef void (*state_cb)(void);/*状态表*/typedef struct{ SM_EVENT event; SM_STATE cur_state; SM_STATE next_state; state_cb cb;}SM_TABLE_T;/*就绪态*/static void standby_state(void){ printf('Standby\r\n');}/*扫描态*/static void scan_state(void){ printf('Scan\r\n');}/*广播态*/static void adv_state(void){ printf('Adv\r\n');}/*连接态*/static void conn_state(void){ printf('Conn\r\n');}/*发起态*/static void init_state(void){ printf('Init\r\n');}/*状态表*/SM_TABLE_T state_table[] ={ {EVENT1, STANDBY, SCAN, scan_state}, {EVENT2, STANDBY, ADV, adv_state}, {EVENT3, STANDBY, INIT, init_state}, {EVENT4, SCAN, STANDBY, standby_state}, {EVENT5, INIT, STANDBY, standby_state}, {EVENT6, ADV, STANDBY, standby_state}, {EVENT7, CONN, STANDBY, standby_state}, {EVENT8 , ADV, CONN, conn_state}, {EVENT9, INIT, CONN, conn_state},};/*状态机*/typedef struct{ SM_STATE cur_state; SM_TABLE_T* table; int size;}SM_T;/*事件处理及状态切换*/void event_handle(SM_EVENT event, SM_T* sm){ assert(sm != NULL && sm->table != NULL); bool find_flag = false; for (unsigned char i = 0; i < sm->size; i++) { if(sm->table[i].event == event && sm->table[i].cur_state == sm->cur_state) { sm->cur_state = sm->table[i].next_state; sm->table[i].cb(); find_flag = true; break; } } if(!find_flag) { printf('Event wrong!\r\n'); }}void main(void){ SM_T state_machine = {.cur_state = STANDBY, .table = state_table, .size = (sizeof(state_table) / sizeof(SM_TABLE_T))}; printf('Init to READY\r\n'); SM_EVENT input_event[] = {EVENT1, EVENT4, EVENT3, EVENT9, EVENT7, EVENT6, EVENT8}; for (char i = 0; i < sizeof(input_event) / sizeof(SM_EVENT); i++) { event_handle(input_event[i], &state_machine); }}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多