“
前沿科技bot 技術專欄作品,你想學的都在這裡
作者:JackD
”
目錄
01 簡單介紹狀态機
02 狀态機的本質
03 狀态機應用場景
01
簡單介紹狀态機
狀态機由狀态寄存器群組合邏輯電路構成,能夠根據控制信号按照預先設定的狀态進行狀态轉移,是協調相關信号動作、完成特定操作的控制中心。以上是百度百科對狀态機的解釋。
在百科的解釋中,我們可以提煉出狀态機的幾個要素:存儲狀态,邏輯電路,預先設定的狀态轉移路徑,外部來的信号,内置的特定操作等。由這些關鍵要素我們可以推斷出以下幾點:
- 狀态資料有預先設定的多種值;
- 邏輯電路是完成内置特定操作的基礎“代碼”(基礎設施),由工程師開發;
- 狀态能在多種值之間轉移;
- 每次轉移都由外部信号觸發;
- 狀态轉移觸發後,會有相應的内置操作。
由以上這些特性共同構成了一個獨立的控制中心,而且這個控制中心與外部各種信号是低耦合的,所有外部信号都要接入一個共同的控制中心,最終也由控制中心完成信号的後續流程。 在Java開發中,狀态機FSM(有限狀态機)是一種常見的設計模式,常常用于一些複雜的業務場景,解決繁瑣雜亂的if...else...代碼段。
“Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.”
對象内部狀态不同會有不同的行為,似乎是不同的類一樣。
以電梯為例,電梯有4種狀态:開門、關門、運作、停止。電梯的動作:開門、關門、運作(上升或下降)、停止(懸停不動)。
Col1 | 開門行為 | 關門行為 | 運作行為 | 停止行為 |
開門 态 | ❌ | ✔ | ❌ | ❌ |
關門 态 | ✔ | ❌ | ✔ | ✔ |
運作 态 | ❌ | ❌ | ❌ | ✔ |
停止 态 | ✔ | ❌ | ✔ | ❌ |
- 開門狀态下,電梯隻有關門行為;
- 關門狀态下,除了關門行為其他行為都有;
- 運作狀态下,隻有停止行為;
- 停止狀态下,有開門行為和運作行為。
狀态圖如下:

狀态機設計模式的好處:
- 降低程式的複雜度;
- 提高程式的可維護性;
- 狀态機模式展現了開閉原則和單一職責原則;
- 每個狀态都是一個子類,增加狀态就要增加子類;修改狀态隻要修改一個類就行了。
這種設計模式将每個狀态的變更後的處理邏輯都做了統一封裝,跟業務代碼耦合,隻接收互相約定的信号(事件)。
02
狀态機的本質
由狀态機的幾個要素我們也可以知道,在一個複雜的業務流程過程中,有多種資料狀态,多種處理動作,以及多種次元的角色。 在這樣複雜業務場景下,如果隻是簡單使用if...else...語句,首先可讀性就非常差,而且維護起來非常困難,甚至是開發人員都沒辦法理清楚自己寫的if..else語句。 如果複雜的業務流程有了變更和新增,那這個維護起來就是個災難,各種複雜問題不得而知。就像下圖一樣:
用if..else..代碼來開發複雜的業務流程,會面臨下面幾個問題:
- 複雜的業務流程,if.else代碼幾乎無法維護;
- 随着業務的發展,業務過程也需要變更及擴充,但if.else代碼段已經無法支援;
- 沒有可讀性,變更風險特别大,可能會牽一發而動全身,給服務帶來S級風險;
- 其他業務邏輯可能也會跟if.else代碼塊耦合在一起,帶來更多的問題。
這時候,狀态機就是個非常好的解決方案,能有效地解決這些問題。 一個狀态機定義以後,在某個狀态下就隻接收固定的Event,也就是執行指定的操作,這樣流程就能按照預期定義的那樣流轉,不會出現亂入的情況,執行了一些在某狀态下不允許執行的操作,也就是說,狀态的流轉都是在控制範圍,不會超出預設的狀态空間。
- 狀态機建立的控制中心是跟外界低耦合的,通過event通信;
- 控制中心所有的狀态都是預設好的,不會超預料;
- 狀态的跳轉都是有設定控制條件的,會按照預設的轉移路徑運動;
- 狀态機還非常容易的擴充和變更,支援因業務的發展而變更或擴充複雜業務流程。
03
狀态機應用場景
狀态機典型的應用有工作流引擎,遊戲中人物狀态變化引擎,訂單交易等。前兩種非常複雜,下面我就簡單以訂單交易這個場景來聊聊狀态機的應用場景以及基于Spring StateMachine的項目。 配置pom依賴:
<dependency> <groupId>org.springframework.statemachinegroupId> <artifactId>spring-statemachine-coreartifactId> <version>2.1.2.RELEASEversion> dependency>
狀态枚舉和事件枚舉:
/*** @author Batman create on 2019-05-07 14:59* 狀态枚舉類*/public enum States { /* 待支付 */ UNPAID, /* 待收貨 */ WAITING_FOR_RECEIVE, /* 結束 */ DONE, /* 退貨中 */ WAITING_FOR_GOODSBACK }/*** @author Batman create on 2019-05-07 15:00*/public enum Events { /* 支付 */ PAY, /* 收貨 */ RECEIVE, /* 退貨 */ GOODS_REJECTED, /* 退款 */ REFUND}
還要配置狀态轉移資訊以及事件處理器邏輯的開發。 擷取完整demo項目,請發送“狀态機”到公衆号背景~
我就知道你“在看”