設計模式的C語言應用 狀態機模式 第二章

2021-09-25 05:12:17 字數 3597 閱讀 6680

狀態(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小時 決定機票的行為 可退票,可改簽等 又例如銀行卡的餘額流水決定者使用者可存款,可借款,可借款金額。又例如工作流審批過...