1. 簡單介紹狀態機java
2. 狀態機的本質redis
3. 狀態機應用場景spring
狀態機由狀態寄存器和組合邏輯電路構成,可以根據控制信號按照預先設定的狀態進行狀態轉移,是協調相關信號動做、完成特定操做的控制中心。以上是百度百科對狀態機的解釋。springboot
在百科的解釋中,咱們能夠提煉出狀態機的幾個要素:存儲狀態,邏輯電路,預先設定的狀態轉移路徑,外部來的信號,內置的特定操做等。由這些關鍵要素咱們能夠推斷出如下幾點:併發
狀態數據有預先設定的多種值app
邏輯電路是完成內置特定操做的基礎「代碼「(基礎設施),由工程司開發spa
狀態能在多種值之間轉移設計
每次轉移都由外部信號觸發code
狀態轉移觸發後,會有相應的內置操做
由以上這些特性共同構成了一個獨立的控制中心,並且這個控制中心與外部各類信號是低耦合的,全部外部信號都要接入一個共同的控制中心,最終也由控制中心完成信號的後續流程。
在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 | 開門行爲 | 關門行爲 | 運行行爲 | 中止行爲 |
---|---|---|---|---|
開門 態 | ❌ | ✔ | ❌ | ❌ |
關門 態 | ✔ | ❌ | ✔ | ✔ |
運行 態 | ❌ | ❌ | ❌ | ✔ |
中止 態 | ✔ | ❌ | ✔ | ❌ |
開門狀態下,電梯只有關門行爲
關門狀態下,除了關門行爲其餘行爲都有
運行狀態下,只有中止行爲
中止狀態下,有開門行爲和運行行爲
狀態圖以下:
狀態機設計模式的好處:
下降程序的複雜度;
提升程序的可維護性;
狀態機模式體現了開閉原則和單一職責原則。
每一個狀態都是一個子類,增長狀態就要增長子類;修改狀態只要修改一個類就好了。
這種設計模式將每一個狀態的變動後的處理邏輯都作了統一封裝,跟業務代碼耦合,只接收相互約定的信號(事件)。
由狀態機的幾個要素咱們也能夠知道,在一個複雜的業務流程過程當中,有多種數據狀態,多種處理動做,以及多種維度的角色。在這樣複雜業務場景下,若是隻是簡單使用if...else...語句,首先可讀性就很是差,並且維護起來很是困難,甚至是開發人員都沒辦法理清楚本身寫的if..else語句。若是複雜的業務流程有了變動和新增,那這個維護起來就是個災難,各類複雜問題不得而知。就像下圖同樣
用if..else..代碼來開發複雜的業務流程,會面臨下面幾個問題:
複雜的業務流程,if.else代碼幾乎沒法維護
隨着業務的發展,業務過程也須要變動及擴展,但if.else代碼段已經沒法支持
沒有可讀性,變動風險特別大,可能會牽一髮而動全身,給服務帶來S級風險。
其餘業務邏輯可能也會跟if.else代碼塊耦合在一塊兒,帶來更多的問題。
這時候,狀態機就是個很是好的解決方案,能有效地解決這些問題。
一個狀態機定義之後,在某個狀態下就只接收固定的Event,也就是執行指定的操做,這樣流程就能按照預期定義的那樣流轉,不會出現亂入的狀況,執行了一些在某狀態下不容許執行的操做,也就是說,狀態的流轉都是在控制範圍,不會超出預設的狀態空間。
狀態機創建的控制中心是跟外界低耦合的,經過event通訊。
控制中心全部的狀態都是預設好的,不會超預料。
狀態的跳轉都是有設定控制條件的,會按照預設的轉移路徑運動。
狀態機還很是容易的擴展和變動,支持因業務的發展而變動或擴展複雜業務流程
狀態機典型的應用有工做流引擎,遊戲中人物狀態變化引擎,訂單交易等。前兩種很是複雜,下面我就簡單以訂單交易這個場景來聊聊狀態機的應用場景以及基於spring statemachine的項目。
配置pom依賴:
<dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-core</artifactId> <version>2.1.2.RELEASE</version> </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 }
歡迎加入技術羣:得到更多java,springboot,redis,kafka圈的好友,共圖技術將來
還要配置狀態轉移信息以及事件處理器邏輯的開發。完整的demo項目,請關注公衆號"前沿科技bot"併發送"狀態機"獲取。