什麼是狀態機?
做產品的時候,我們總能遇到一些比較複雜的邏輯問題,而普通的流程圖,或時序圖對於對象和狀態的解讀缺乏直觀的描述。
這時,推薦使用簡單的狀態圖來對邏輯問題進行描述。
在開發過程中,如果有邏輯關係比較混亂的,我們就可以考慮使用有限狀態機來解決問題。
狀態機,表示某幾種狀態之間的切換。描述一個對象從一個狀態,經過一個事件驅動轉變爲另一個狀態的過程,叫做一次狀態遷移,一個對象所具備的所有狀態遷移過程叫做狀態機。
因爲狀態機的狀態是有限的,所以一般上也叫有限狀態機(Finite State Mache)。
有限狀態機,(英語:Finite-statemachine, FSM),又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行爲的數學模型。
有限狀態機是一種用來進行對象行爲建模的工具,其作用主要是描述對象在它的生命週期內所經歷的狀態序列,以及如何響應來自外界的各種事件。在計算機科學中,有限狀態機被廣泛用於建模應用行爲、硬件電路系統設計、軟件工程,編譯器、網絡協議、和計算與語言的研究。
狀態機的作用
利用狀態機可以精確地描述對象的行爲,從對象的初始狀態起,開始響應事件並執行某些動作,這些事件引起狀態的轉換,對象在新的狀態下又開始響應狀態和執行動作,如此連續進行直到終結狀態。
1、不需要每個接口都校驗當前狀態:直接數據庫配置某個狀態,加某個操作,才能進行下去,如果不對的狀態進行該操作,會報錯
2、同一個接口配置不同的流程:同一個如審批通過的接口,不同狀態下審批不通過,需要走不同的流程,如審批中審批不通過,走改變狀態的流程,變更審批中審批不通過,走回退歷史的版本數據的流程,如果不用狀態機,則需要分開寫2個接口,或者在一個接口裏走if else,考慮到複雜的訂單狀態變遷觸發節點,可能if-else會非常多,比如某5種狀態下的同一個接口走不同的流程
3、實現流程可配製化,高內聚,集中配置,直接在數據庫更改配置信息,可維護性和擴展性強
4、易變更,快速修改
5、易使用,極大簡化前端的代碼,是否可以刪除,變更按鈕的顯示和隱藏通過後端返回
狀態機由什麼組成?
-
狀態:表示一個模型在生存期內的狀況
-
轉換:表示兩個不同狀態之間的聯席
-
事件:是在某個時間產生的
-
活動:是在狀態機中進行的一個非原子的執行,有一系列動作組成
-
動作:是一個可執行的原子計算,它導致狀態的變更或者返回一個值
如何畫狀態圖?
當需要描述一個對象或系統的行爲狀態時,相比於直接的語言描述,更推薦使用狀態機表或狀態機圖的形式。
首先看一下圖形中的基本元素:
分析需求時需要了解以下六種元素:
-
起始
-
終止
-
現態
-
次態(目標狀態)
-
動作
-
條件
這樣,我們就可以完成狀態機圖了,來看一個具體的案例吧:
1.現態:是指當前所處的狀態。
2.條件:又稱爲“事件”,當一個條件被滿足,將會觸發一個動作,或者執行一次狀態的遷移。
3.動作:條件滿足後執行的動作。動作執行完畢後,可以遷移到新的狀態,也可以仍舊保持原狀態。動作不是必需的,當條件滿足後,也可以不執行任何動作,直接遷移到新狀態。
4.次態:條件滿足後要遷往的新狀態。“次態”是相對於“現態”而言的,“次態”一旦被激活,就轉變成新的“現態”了。
注意:
1、注意區分“程序動作”和“狀態”。如何區分“動作”和“狀態”?
“動作”是不穩定的,即使沒有條件的觸發,“動作”一旦執行完畢就結束了;
“狀態”是相對穩定的,如果沒有外部條件的觸發,一個狀態會一直持續下去。
2、狀態劃分避免缺漏,這樣會導致跳轉邏輯不完整。查看狀態圖或者狀態表是很有必要的,儘量讓設計方案足夠完善。
如何做狀態機表?
先看案例,下面的狀態機圖展示了一個文件的狀態流轉。
將狀態圖轉爲狀態表有多種製表法,如果以縱座標區分,有兩種:
左邊的狀態表的縱座標爲初始狀態,橫座標爲終止狀態。
右邊的狀態表的縱座標爲動作條件,橫座標爲終止狀態。
如果動作多且複雜的情況下,建議採用右側表格方式,會更清晰。
狀態機圖的使用場景
狀態機圖常應用在程序的設計過程中,使用清晰明瞭的狀態機圖設計代碼邏輯架構,再使用編程語言去實現。
也可以畫一個狀態機圖來展示某崗位的工作:
開發實現狀態機的設計實例
實例:電商平臺訂單狀態設計
狀態機的技術實現
首先會有2個表:flow和flow_picker表:
flow表:主要用於存放不同的流程的名字,主要會有個id,訂單走一個流,退貨單走一個流
flow_picker表:主要是每個業務創建的時候,會關聯到哪個flow,就是關聯到哪個流程id裏,會通過來源,渠道,類型,等級等等條件,篩選出這個訂單,關聯的flow,存入訂單表裏的flow_id字段
配置流程的表:
先會根據訂單的flow_id篩選出走哪個流程,再根據來源狀態 source_status,操作operation_value,到達目標狀態target_status,執行action_name,
action_name是自己配置的,action_name裏面的類就是不同流程,執行的代碼
根據這個配置,初始化時注入所有的action,可以調到數據庫對應的配置的aciton類,同一個接口,可執行多個流程就完成了。