1. 程式人生 > >整理:狀態機的兩種寫法對比

整理:狀態機的兩種寫法對比

    狀態機可以用兩種方法實現:豎著寫(在狀態中判斷事件)和橫著寫(在事件中判斷狀態)。這兩種實現在本質上是完全等效的,但在實際操作中,效果卻截然不同。

==================================

豎著寫(在狀態中判斷事件) C程式碼片段

==================================

    cur_state = nxt_state;

    switch(cur_state)

    {                  //在當前狀態中判斷事件

        case s0:       //s0狀態

            if(e0_event)

           {    //如果發生e0事件,那麼就執行a0動作,並保持狀態不變;

執行a0動作;

                //nxt_state = s0;       //因為狀態號是自身,所以可以刪除此句,以提高執行速度。

            }

            else if(e1_event)

            {   //如果發生e1事件,那麼就執行a1動作,並將狀態轉移到s1態;

執行a1動作;

                nxt_state = s1;

            }

            else if(e2_event)

            {  //

如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

執行a2動作;

                nxt_state = s2;

            }

            break;

        case s1:         //s1狀態

            if(e2_event)

             {  //如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

執行a2動作;

                nxt_state = s2;

            }

            break;

        case s2:         //

s2狀態

            if(e0_event)

           {   //如果發生e0事件,那麼就執行a0動作,並將狀態轉移到s0態;

執行a0動作;

                nxt_state = s0;

            }

    }

==================================

橫著寫(在事件中判斷狀態) C程式碼片段

==================================

//e0事件發生時,執行的函式

void e0_event_function(int * nxt_state)

{

    int cur_state;

   cur_state = *nxt_state;

    switch(cur_state)

   {

        case s0:                 

        case s2:

執行a0動作;

            *nxt_state = s0;

    }

}

//e1事件發生時,執行的函式

void e1_event_function(int * nxt_state)

{

    int cur_state;

  cur_state = *nxt_state;

    switch(cur_state)

    {

        case s0:                     

執行a1動作;

            *nxt_state = s1;

    }

}

//e2事件發生時,執行的函式

void e2_event_function(int * nxt_state)

{

    int cur_state;

    cur_state = *nxt_state;

    switch(cur_state)

    {

        case s0:                      

        case s1:

執行a2動作;

            *nxt_state = s2;

    }

}

上面橫豎兩種寫法的程式碼片段,實現的功能完全相同,但是,橫著寫的效果明顯好於豎著寫的效果。理由如下:

    1、豎著寫隱含了優先順序排序(其實各個事件是同優先順序的),排在前面的事件判斷將毫無疑問地優先於排在後面的事件判斷。這種if/else if寫法上的限制將破壞事件間原有的關係。而橫著寫不存在此問題。

    2、由於處在每個狀態時的事件數目不一致,而且事件發生的時間是隨機的,無法預先確定,導致豎著寫淪落為順序查詢方式,結構上的缺陷使得大量時間被浪費。對於橫著寫,在某個時間點,狀態是唯一確定的,在事件裡查詢狀態只要使用switch語句,就能一步定位到相應的狀態,延遲時間可以預先準確估算。而且在事件發生時,呼叫事件函式,在函式裡查詢唯一確定的狀態,並根據其執行動作和狀態轉移的思路清晰簡潔,效率高,富有美感。

總之,我個人認為,在軟體裡寫狀態機,使用橫著寫的方法比較妥帖。

豎著寫的方法也不是完全不能使用,在一些小專案裡,邏輯不太複雜,功能精簡,同時為了節約記憶體耗費,豎著寫的方法也不失為一種合適的選擇。