狀態(state)模式是c語言實現相當常用的模式,也是能夠在c語言***現出來的最顯性的模式之一。在物件導向裡,狀態模式允許乙個物件在內部狀態改變的時候改變其行為。
狀態用法很多,最常見的是狀態機,分為無限狀態機和有限狀態機。
有限狀態機 finite-state machine, fsm, 輸入集合和輸出集合都是有限的,並只有有限數目的狀態。 一般說到狀態機即是對有限狀態機的簡稱。
無限狀態機 infinite-state machine,ism ,輸入和輸出集合無線,狀態數目無限的狀態機。
在c語言裡,狀態模式有且僅有一種經典用法,就是有限狀態機(fsm)的實現。實現的方式極為突出明顯,大部分情況都能直接照搬框架。
狀態機最常見的使用場景是實現協議。通常協議會有幾個核心狀態機描述。
狀態機示例1
有乙個燈,按下開按鈕,就會開燈,按下關按鈕就會關燈。這就是乙個很典型的簡單的有限狀態機。簡單的描述有2個狀態,關燈[state_off],亮[state_light_on] 。有兩個事件,開和關按鈕。這兩個事件促使狀態機間的轉換。
狀態機示例2
有乙個燈,按下開按鈕,就會開燈,按下關按鈕就會關燈。和一般等不同的是,兩次開之間的燈的明暗不一樣。也就是說,第一次開的時候,是高亮,關燈後,再開是低亮,下次再開是高亮,迴圈往復。
這就是乙個很典型的簡單的有限狀態機。簡單的描述有3個狀態,關燈[state_off],高亮[state_high_light],低亮[state_low_light]。
以狀態機示例1為目標,如果用if/switch/case來,就沒有什麼設計和模式的意義,那只是最普通的流程開發技能。以下是簡單狀態機模式實現,適用於轉移條件單一,對結果很確定的狀態機。
#define state_off 0
#define state_light_on 1
#define state_max 2
#define evetn_btn_off
#define evetn_btn_on
#define evetn_max
int light_fsm_******_table[state_max][evetn_max] =
;int light_fsm_event(int cur_stat, int event)
int main()
以上**有幾個要點
1. 狀態轉移陣列。由於簡單模式某種狀態下發生某事件的結果是確定的,所以陣列的值就是下乙個狀態。
2. 需要乙個狀態處理的封裝函式light_fsm_event。裡面除了轉移狀態,可以增加擴充套件處理。不然簡單模式應用就很侷限。比如可以在light_fsm_event裡面加入
if(next_state == state_light_on)
大型一點的專案,比如複雜協議的實現,乙個狀態轉移到下乙個狀態的情況是比較複雜的,無法用當前狀態和事件簡單確定,所以一般需要函式。
以下**實現了狀態機示例二,為樣例**,未執行實驗過。
#define state_depend 4
#define state_off 0
#define state_high_light 1
#define state_low_light 2
#define state_max 3
#define evetn_btn_off
#define evetn_btn_on
#define evetn_max
int last_state = state_low_light;
int last_light_state = state_low_light;
struct light_fsm [state_max][evetn_max] =
, /*evetn_btn_off*/
, /*evetn_btn_on*/
}//state_high_light
, /*evetn_btn_off*/
, /*evetn_btn_on*/
}//state_low_light
, /*evetn_btn_off*/
, /*evetn_btn_on*/
}}int lfsm_ignore(int cur_stat, int event)
int lfsm_btn_on(int cur_stat, int event)
else if(last_light_state == state_low_light)
else
}int lfsm_btn_off(int cur_stat, int event)
int light_change_state(int cur_stat, int next_state,int event)
;
//other state change related handlings, maybe use current state and next state, or event type
last_state = cur_stat;
cur_stat = next_state;
return 0;
} //other event type related handlings
return 0;
}int light_fsm_event(int cur_stat, int event)
if(light_fsm[cur_stat][event].next_state == state_depend)
else
light_change_state(next_state, cur_stat, event);
}int main()
普通模式的狀態機的幾個關鍵點1. 狀態機陣列由狀態事件處理函式+下乙個狀態陣列代替簡單模式的下乙個狀態的陣列
2. 由於在特定模式特定事件發生時,有的情況不能確定下乙個狀態的跳轉,有的情況可以。所以下一狀態有個特殊值為state_depend。如果遇到這個值,就從狀態變化函式裡獲得下乙個狀態。否則按照狀態機陣列設定的狀態。
3. 設定乙個狀態state_max用來表示錯誤事件,加上乙個lfsm_ignore函式來處理這種情況。比如本例中,設定evetn_btn_on不可能在開燈的時候發生。
5. 一般情況下,有乙個全域性變數儲存當前狀態和上乙個狀態。
物件導向語言實現狀態機通常是乙個狀態的抽象父類,每個狀態有乙個子類和乙個例項。c語言裡狀態轉移表的函式指標是通過狀態子類的成員函式實現。其他的寫法思路比較接近。
最常見的複雜狀態機是為了實現網路協議。比如ospf,可以參見我寫的另外一篇文章zebra中fsm編寫總結.doc
1. 專案開發裡最常見的使用為普通狀態機,網路協議使用的複雜狀態機也是在普通狀態機上新增一些特性而來,基本特徵是非常類似的。
2. c語言實現狀態機的模式是非常固定的。狀態轉移表和核心的狀態轉移函式是核心。普通狀態機的幾個要素,不管在初始設計中有沒有使用到,建議都寫上。
設計模式的C語言應用 編碼實踐 狀態機模式2
include stdafx.h 基於state mode 1 上的 示例2 有乙個燈,按下開按鈕,就會開燈,按下關按鈕就會關燈。和一般等不同的是,兩次開之間的燈的明暗不一樣。也就是說,第一次開的時候,是高亮,關燈後,再開是低亮,下次再開是高亮,迴圈往復。這就是乙個很典型的簡單的有限狀態機。簡單的描...
設計模式 狀態模式(有限狀態機)
狀態模式適用的情況 乙個context物件根據其所處的狀態改變其行為。在狀態模式中,我們通過建立不同的state物件來表示不同的狀態,而context物件則根據不同的state物件表現出不同的行為。狀態模式將不同的狀態結構化,以避免過多的 if else 和 switch case 等樣版 用設計模...
設計模式(三)狀態機
狀態模式 主要解決某個物件具有不同的狀態,根據狀態的不同具有不同的行為。狀態的變化影響這物件的行為的問題。例如航空訂票,機票有不同的狀態,根據不同的狀態 已登機,未登機,起飛前24小時 決定機票的行為 可退票,可改簽等 又例如銀行卡的餘額流水決定者使用者可存款,可借款,可借款金額。又例如工作流審批過...