欢迎大家来到IT世界,在知识的湖畔探索吧!
介绍:
状态模式是一种行为模式,它与有限状态机的概念紧密相关;其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。
作用:
将业务模型抽象成一个有限状态机,减少大量的switch-case和if-else的使用,使得代码逻辑清晰,结构规整;
类比:
智能手机的按键和开关会根据设备当前状态完成不同行为:
- 当手机处于解锁状态时, 按下按键将执行各种功能。
- 当手机处于锁定状态时, 按下任何按键都将解锁屏幕。
- 当手机电量不足时, 按下任何按键都将显示充电页面。
以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);
}
}
欢迎大家来到IT世界,在知识的湖畔探索吧!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/37228.html