天天看點

土制狀态機在工作流引擎中的應用

/**

  * @author : ahuaxuan

  * @date 2009-10-27

  */

很早之前(應該是一年以前),ahuaxuan在用dfa實作文字過濾一文中使用确定有限自動機實作了詞典的高速查詢。其實在當時那段時間裡,由于對狀态機有了一定的研究,ahuaxuan也觸類旁通的了解了工作流引擎的核心體制。于是當時就用python寫了一個小巧的工作流引擎的示例,在這之前ahuaxuan沒有看過任何工作流引擎的實作,該實作純屬思維的自我延伸。

現在我來說說我的實作。

狀态機的本質是狀态的遷移,即從a狀态+某個動作===》b狀态。到這裡我們還要來看看這張圖。

從這張圖中我們可以看到,狀态(大寫字母)+動作(小寫字母)可以到達新的狀态。那麼對于程式員來說,我們要做的就是将這種機制用程式表達出來。比如說我們最常想到的是什麼?矩陣!

這很好了解,但是對于工作流引擎來說,由于狀态的遷移涉及到:目前狀态+動作+條件===》新狀态。

是以用二維的矩陣無法表示出這種邏輯。那麼我們可以将矩陣中的元素替換為條件數組。

這樣,我們可以通過目前狀态+動作得到一個條件數組,然後再周遊這個條件數組,條件數組中的元素即是條件和滿足條件的下一個狀态(雖然本質上是一個三維數組,但是在這裡還是看成矩陣+數組元素比較符合邏輯)。

土制狀态機在工作流引擎中的應用

這裡需要畫一個圖,一個矩陣,矩陣中的元素是一個條件數組

沒錯,這是一種方案,但是這裡有一個問題,那就是每次做狀态遷移的時候,我們必須知道某個狀态在矩陣一維上的index,已經某個動作在矩陣二維上的index.有了這兩個index我們才能得到條件數組。是以這裡還有一個繁瑣的轉換操作操作。來看一段僞代碼:

核心流程大概就是這樣,當

那麼除了矩陣這種資料結構,我們還有其他的資料結構可以用來表示: “目前狀态+動作+條件===》新狀态”嗎。

當然有,那就是使用樹結構。在了解了三維數組的實作之後,再來看樹實作,應該和容易了,那就直接上圖, 将上圖的矩陣轉換成樹結構之後,我們可以得到如下的樹結構。

土制狀态機在工作流引擎中的應用

那現在我們來審視一下現在的問題,打個比方,我們現在手裡有兩張牌,一張是狀态a,一張是動作a,我們如何通過這兩種牌來得到條件集合呢,最簡單的方法是首先周遊第二層節點,找到a,然後再周遊a的子節點,找到a。通過兩次for循環找到了條件集合,而條件集合中包含着下一個狀态。

那麼有沒有更簡單更快速的方式可以直接找到條件集合,而直接跳過兩次周遊呢。有,ahuaxuan的想法是tree+hash.也就是通過a的hash值,我們可以直接找到tree上的a節點。然後再通過a的hash值,我們可以直接找到a的子中的a節點。得到a節點之後我們就可以條件集合。那麼我們可以用什麼樣的資料結構來實作一個這樣的模型呢。這裡面有hash運算,那麼我們首先選擇hashmap來建立這麼一顆樹。

我們來看一下這個定義: 

那麼我們如何根據a,和a來得到一個條件集合呢? 

通過這樣的方式,我們就可以根據目前狀态和目前的動作得到一個條件集合。然後周遊這個條件集合就是找到滿足“輸入“的條件,該條件會指向下一個狀态。

我們來看一下代碼實作:

首先我們來構造這麼一個狀态機: 

接着我們來看看如何根據這個狀态機來做狀态遷移: 

通過這種tree + hash的方式,我們可以很容易的進行狀态的遷移,不需要那麼多for循環。但是for循環确實有這樣的實作。

今天早上下載下傳了osworkflow的代碼,稍微看了一下abstractworkflow的doaction方法。

發現osworkflow就是通過循環來實作狀态的遷移的,比如說上圖中樹結構的狀态可以用以下僞代碼: 

通過這種方式,使用者傳入inputstatename和inputactionname, osworkflow得到了一組transition,并根據條件選擇某個transition, 這樣也實作了狀态的轉移。

從這裡面可以看出,osworkflow是利用廣度優先的原則,先找到符合條件的state,然後再找到符合條件的action,以此類推。

說到這裡,通過這種狀态機實作工作流引擎的方式基本的完全的,較為清晰的呈現在我們眼前了。

未完待續