有限狀態機(FSM)是表示有限個狀態及在這些狀態之間的轉移和動作等行為的數學模型,在計算機領域有着廣泛的應用。通常FSM包含幾個要素:狀態的管理、狀態的監控、狀態的觸發、狀態觸發后引發的動作。本文主要闡述一下狀態機的幾種設計方法。
1:switch case/if else設計方法
curEvent = getEvent(); curState = getCurState(); switch(curState) { case state1: { switch(curEvent ) { TODO... setCurState(); break; } break; } ... }
這種設計方法最簡單,通過一大堆判斷來處理,適合小規模的狀態切換流程,但如果規模擴大難以擴展和維護。
2:基於表結構的狀態機設計方法:建立相應的狀態表和動作查詢表,根據狀態表、事件、動作表定位相應的動作處理函數,執行完成后再進行狀態的切換。
一個通用的狀態機處理模塊的設計如下:
/*狀態表注冊*/
void FSM_Regist(FSM_T* pFsm,STATE_TABLE_S* pStateTable) { pFsm->FsmTable = pStateTable; return; } /*狀態遷移*/ void FSM_MoveState(FSM_T* pFsm,int state) { pFsm->curState = state; return; }
/*事件處理*/ void FSM_EventHandle(FSM_T* pFsm,int event) { ACT_TABLE_T* pActTable = NULL; ActFun eventActFun = NULL; /*獲取當前狀態動作表*/ pActTable = FSM_getActTable(pFsm); /*獲取當前動作函數*/ for(int i=0;i<MAX_ACT_NUM;i++) { if(event == pActTable[i].event) { eventActFun = pActTable[i].eventActFun; break; } } /*動作執行*/ if(eventActFun) { eventActFun(pFsm); } }
假設我們的狀態圖如下:
相應的狀態機設置如下:
/*狀態1的動作表*/ ACT_TABLE_T state1ActTable[] = { {EVENT1,state1Event1Fun}, {EVENT3,state1Event3Fun}, }; /*狀態2的動作表*/ ACT_TABLE_T state2ActTable[] = { {EVENT2,state2Event2Fun}, }; /*狀態表*/ STATE_TABLE_T FsmTable[] = { {STATE1,state1ActTable}, {STATE2,state2ActTable}, }; int main(int argc, _TCHAR* argv[]) { FSM_T fsm; /*狀態表注冊*/ FSM_Regist(&fsm,FsmTable); FSM_MoveState(&fsm,STATE1); FSM_EventHandle(&fsm,EVENT1); FSM_EventHandle(&fsm,EVENT2); return 0; }
/*客戶端提供的狀態處理函數*/ void state1Event1Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE2);
return; } void state1Event3Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE3);
return; } void state2Event2Fun(void* pFsm) { FSM_MoveState((FSM_T*)pFsm,STATE3);
return; }
通過設計一個通用的基於表結構的狀態機模塊,針對不同的狀態圖,我們只需要根據狀態圖得到其狀態表結構,然后通過FSM_Regist注冊,就可以方便的使用了狀態機的功能了。這種機制便於我們添加新的狀態流程,並且可以很好的進行分層狀態機的設計。
轉載請注明原始出處:http://www.cnblogs.com/chencheng/archive/2012/06/25/2562660.html