使用列舉實現狀態機來優雅你的狀態變更邏輯

碼農小胖哥發表於2019-08-28

福利

現在關注微信公眾號:碼農小胖哥, 傳送關鍵字【抽獎】進行抽獎,可有機會獲取實體程式設計書籍。活動只剩下3天了抓緊參與!【本次抽獎截止到本週末】

前言

相信不少java開發者寫過狀態變更的業務,比如訂單流程、請假流程等等。一般會搞一個狀態標識來標識生命週期的某個階段。很多人會寫這種邏輯:

81c16edb01abf9a6905287d6d7c1465f.png

如果流程幾十個豈不是要if到爆炸。還有這“0”、“1”是幾個意思?

優化的辦法當然可以使用設計模式中的狀態模式來搞,允許一個具有狀態的物件根據其狀態封裝同一物件的不同行為。我們可以程式設計狀態之間的轉換,然後定義單獨的狀態:

3a7712fe25ea715da4cce999f7e08372.png

但是這種操作會增加過多的狀態物件依賴。那麼有沒騷操作呢?當然有。我們先來了解了解狀態機。

狀態機

狀態機全稱有限狀態機,因為一般的狀態機的狀態都是離散而且可列舉的,這就是有限的原因。狀態機表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。通俗的描述狀態機就是定義了一套狀態変更的流程:狀態機包含一個狀態集合,定義當狀態機處於某一個狀態的時候它所能接收的事件以及可執行的行為,執行完成後,狀態機所處的狀態變化可以被感知。一般包含以下幾個概念:

  • 狀態 太廢話了我,狀態機沒有狀態還能叫狀態機。
  • 事件 狀態機的狀態變更肯定是通過觸發一個事件引起的。
  • 行為 觸發了之後執行的業務邏輯。比如說訂單未支付狀態到支付狀態的變更需要走的業務,寫流水、修改賬戶餘額等。
  • 變更 一個狀態被一個事件觸發執行了某些行為到達了另外一個狀態的過程。

1786d6c5729de8738d2eeb8bb3fbbe49.png

上圖就是個變更的過程示意。接下來該說另一個東西java列舉了。

Java中的列舉

一個Java的列舉是一種定義的一類常量列表的特殊型別的類。是JDK 1.5中引入的新特性。 列舉在JDK中其實就是被設計成了單例模式,所以是不允許外部對其進行例項化的,列舉型別的例項化都是在其載入的時候JVM幫我們完成的。這是Java虛擬機器規範明確規定的,保證了執行緒的安全性。由於Java列舉隱式實現了列舉超類java.lang.Enum,因此無法實現另一個類,但是可以實現介面。可以宣告抽象方法由具體的內部列舉來實現。我們定義一個顏色列舉來看看:

96946720c5e689dcefa9c25dc0501491.png

我們可以通過 Colorful.RED.colorName() 直接拿到顏色的名稱,非常方便而且語義化。

接下來我們將結合實際開發場景來實現一個簡單列舉型別的狀態機來處理業務。

實戰操作

訂單派送到收貨這個場景,我們考慮如下單純的場景:

68f550216ebb615fe4a4d77b0d596054.png

經歷排程到派送最後到收貨這個簡單過程,我們可以定義如下狀態列舉:

91cfaad5231a51143a78e155d2c5c80c.png

因為排程是初始狀態,所以其prevState方法指向自己,因為收貨時終止狀態所以其nextState指向自己。通過定義這兩個指標來進行操作所需要的流程。當然實際生產要結合你自己的業務來做。

然後我們訂單流程就可以這樣搞(省略getter和setter):

91cfaad5231a51143a78e155d2c5c80c.png

我們來簡單測試一下:

8da6c5308d0105cc45ad62a3f9e8d421.png

經過兩次的流轉,貨物成功到達買家的手中,狀態也正確的進行了變更,而且可維護性也得到了保證,只需要變更列舉流程。好了今天就到這裡,希望大家多多關注。

相關文章