有限狀態機與狀態模式


狀態機

   

       在理解狀態機之前,總是把狀態里簡單地理解為狀態模式,最近,我仔細分析了狀態機的實現機制,發現狀態機和狀態模式還是有很大的不同。

       一,狀態模式是具體的,針對每個需求有一個狀態集,並為其實現特有的遷移機制。狀態機是抽象的,不是針對特定的需求,而是對各種與相關的問題的進一步抽象,那么用狀態機回頭去實現狀態模式的時候,只需要關注問題本身,而不用去關心如何實現,也就是說你只需要繪制出狀態遷移圖,狀態機就能幫你去實現。

       二,狀態模式的是命令式的,我們必須一步一步地去實現狀態之間如何遷移,以及遷移過程中需要做一些額外的事情。狀態機是聲明式的,使用狀態機,你只需要聲明狀態及狀態的遷移路線,而不需要去提供執行層面的命令,狀態機自動幫你去做。

       三,狀態模式容易理解,狀態機確實不是那么容易理解,估計很多人會想我一樣,認為其沒有什么差別,這是不對的。(這也算是一個區別,哈哈)

       區分了這么多,言歸正傳,來分析一下一個典型的狀態機的實現,首先簡要看一下類圖:

       一,Event,顧名思義是事件的意思,在狀態遷移過程中所發生的事情,分為主動事件ActiveEvent(對應原著里的Command),被動事件PassiveEvent。

       主動事件是進入某個狀態以后自動往狀態機以外發送信息的事件,被動事件是被狀態機接受處理完成狀態遷移的事件。

       二,CommandChannel,命令通道用來接收被動事件和發送主動事件,被控制器所持有,特定的需求可以實現各自具體的命令通道。

       三,State,狀態和狀態模式里的每個具體狀態對應,區別是狀態模式里的每個狀態對應一個特定的狀態類(命令式,有效的信息有類名,遷移方法),而這里的State是一個簡單的結構,主要包括名稱,遷移表(對應前者的類名和遷移方法),主動事件表(進入該狀態以后自動調用),自動激發事件表,在主動事件調用完畢以后,主動狀態機本身發送被動事件,用途是有的狀態只是一個中間臨時狀態,會被自動遷移到下一個狀態,比如一扇門而言:Open事件導致門進入Opening(正在打開)狀態,這個狀態會做一個動作(角度慢慢擴大),然后自動遷移到Opened(已經打開)狀態,那么Opening就會擁有一個Open的自動激發事件,在其處理的結尾將這個事件發送到狀態機以自動切換到Opened狀態

       三,Transition,狀態切換路徑,包含EventCode(事件源,指定了當前狀態下對該事件感興趣),Source(源狀態),Trigger(觸發器),Target(目的狀態)。

       四,StateMachine,到狀態機了,狀態機本身很簡單,包含Start(狀態機的起始狀態),AllStates(該狀態機的所有可能的狀態)。

       五,Controller,控制器負責接收外部事件Handle(eventcode),指導狀態機完成窗台遷移,包括CurrentState(狀態機內部的當前狀態),Machine(狀態機),CommandChannel(命令通道)。

       以上介紹了簡單的類圖,值得提醒的一點就是,從靜態結構看,唯一可以擴展的地點就是CommandChannel,這個類有一個DoSend方法需要實現,每個具體的應用實現這個方法來根據其狀態參數做具體的操作。

       下面從源代碼的角度來觀察:

       一,抽象事件

   

       二,主動事件

       三,被動事件

       四,       狀態

   

       五,狀態機

       六,遷移

七,控制器

以上是詳細的代碼,有興趣看完的話,我也是醉了(同道中人啊)。下面我做兩個簡單的例子介紹,都是關於門的例子第一個例子如下:有兩個狀態:開和關,在開的狀態下接受到Close事件,則遷移到關狀態,在關狀態下,接受到Open事件,則遷移到開狀態。測試如下:

代碼是不是"聲明式"味道的啊:)。

第二個例子在這個例子上增加兩個狀態:正在關閉,正在打開,如下:

測試代碼如下:

參考書目《領域特定語言》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM