一、為什么引入有限狀態機?
最近做一個項目,項目中很多實體(Entity),每個實體都有很多狀態(State),各狀態會經過不同事件(Event)觸發后轉換到另一個狀態。這些事件包括但不限於:用戶頁面點擊觸發,生效時間或失效時間到達,其他依賴實體狀態變更等。在狀態變更后還會有一系列動作(Action)處理。一旦相互依賴實體或實體本身狀態增多,狀態轉換變多,處理這些狀態的業務代碼也會分散在各處,代碼處理很容易漏掉,維護成本很高。所以考慮引入有限狀態機。
二、什么是有限狀態機?
有限狀態機,也稱為FSM(Finite State Machine),其在任意時刻都處於有限狀態集合中的某一狀態。當其獲得一個輸入字符時,將從當前狀態轉換到另一個狀態,或者仍然保持在當前狀態。任何一個FSM都可以用狀態轉換圖來描述,圖中的節點表示FSM中的一個狀態,有向(方向表示從一個初態轉換到次態)加權(權表示事件)邊表示輸入字符時狀態的變化。如果圖中不存在與當前狀態與輸入字符對應的有向邊,則FSM將進入“消亡狀態(Doom State)”,此后FSM將一直保持“消亡狀態”。狀態轉換圖中還有兩個特殊狀態:狀態1稱為“起始狀態”,表示FSM的初始狀態。狀態6稱為“結束狀態”。
在啟動一個FSM時,首先必須將FSM置於“起始狀態”,然后觸發一系列時間,最終,FSM會到達“結束狀態”或者“消亡狀態”。
圖1:狀態轉換圖
說明:
在通常的FSM模型中,一般還存在一個“接受狀態”,並且FSM可以從“接受狀態”轉換到另一個狀態,只有在識別最后一個字符后,才會根據最終狀態來決定是否接受所輸入的字符串。此外,也可以將“其實狀態”也作為接受狀態,因此空的輸入序列也是可以接受的。
1. 狀態機要素
狀態機可歸納為4個要素,即現態、條件、動作、次態。“現態”和“條件”是因,“動作”和“次態”是果。詳解如下:
①現態:是指當前所處的狀態。
②條件:又稱為“事件”。當一個條件被滿足,將會觸發一個動作,或者執行一次狀態的遷移。
③動作:條件滿足后執行的動作。動作執行完畢后,可以遷移到新的狀態,也可以仍舊保持原狀態。動作不是必需的,當條件滿足后,也可以不執行任何動作,直接遷移到新狀態。
④次態:條件滿足后要遷往的新狀態。“次態”是相對於“現態”而言的,“次態”一旦被激活,就轉變成新的“現態”了。
我們可以用狀態表了表示整個過程,如下圖所示。
圖2:狀態轉換表
2. 有限狀態機表示方法
①狀態轉換圖,例如圖1
②狀態轉換表,例如圖2
三、有限狀態機實現方式
1. Java switch case 或者 Scala 模式匹配實現
2. Java枚舉實現
Java枚舉實現有限狀態機
3. 設計模式:狀態模式實現
4. 使用stateless4j實現
github地址:https://github.com/stateless4j/stateless4j
5. Spring Statemachine實現
github地址:https://github.com/spring-projects/spring-statemachine
6. Akka FSM 狀態機實現
github地址:https://github.com/akka/akka
7. 通過squirrel-foundation實現
github地址:https://github.com/hekailiang/squirrel
自己做了些實例及封裝:https://github.com/barrywang88/fsm