從工作流狀態機實踐中總結狀態模式使用心得
狀態模式好像是很簡單的模式,正因為狀態好像是個簡單的物件,想複雜化實現設計模式就不是容易,誤用情況很多。
我個人曾經設計過一個大型遊戲系統的遊戲狀態機,遊戲狀態可以說是遊戲設計的主要架構,但是由於系統過分複雜
和時間倉促,並沒有真正實現狀態模式。
目前在實現一個電子政務專案中,需要進行流程狀態變化,在電子政務設計中,我發現,如果一開始完全按照工作流
規範開發,難度很大,它和具體專案實踐結合無法把握,而且工作流規範現在有wfmc,還有bpml,選擇也比較難。因
此,我決定走自創的中間道路。
因為,我需要做一個狀態機API,或者說狀態機框架,供具體系統呼叫:類如公文流轉應用或資訊發報送應用等。
好的狀態模式必須做到兩點:
1. 狀態變化必須從外界其它邏輯劃分出來。
2. 狀態必須可方便擴充,對其它程式碼影響非常小。
要做到這兩點,必須先明確狀態變化機制,狀態變化實際是由Event事件驅動的,可以認為是Event-condition-State,
在MVC模式一般是Event-condition-Action實現。狀態模式需要封裝的是Event-condition-State中的condition-State
部分。
清晰理解狀態和流程的關係也非常重要,因為狀態不是孤立的,可以說和流程是點和線的關係,狀態從一個方面說明
了流程,流程是隨時間而改變,狀態是擷取流程某個時間片。因此,必須明白使用狀態模式實現狀態機實際是為了更
好地表達和說明流程。
狀態和流程以及事件的關係如下:
圖中表示了是事件改變了流程的狀態,在業務邏輯中,經常發生的是事件,如果不使用狀態模式,需要在很多業務邏
輯處實現事件到狀態判定和轉換,這有很多危險性。
最大的危險是系統沒有一個一抓就靈的主體結構,以那個遊戲系統為例,在沒有狀態模式對狀態提煉的情況下,狀態
改變由每個程式設計師想當然實現,導致每個程式設計師開發的功能在整合時就無法除錯,因為這個程式設計師可能不知道那個程
序員的程式碼在什麼執行條件下改變了遊戲狀態,結果導致自己的程式碼無法執行。
這種現象實際上拒絕了專案管理的協作性,大大地拖延專案進度(程式設計師之間要反覆商量討論對方程式碼設計)。從這
一點也說明,一個好的架構設計是一個專案快速成功完成的基礎技術保證,沒有這個技術基礎,再先進的專案管理手
段也是沒有效率的,或者是笨拙的。
狀態模式對於很多系統來說,確實是架構組成一個重要部分。
下面繼續討論如何實現一個好的狀態模式,為了實現好的狀態模式,必須在狀態模式中封裝下面兩個部分:
1. 狀態轉換規則(行為)
2. 狀態屬性(屬性)
狀態轉換行為有兩種劃分標準:
1. run和next兩個行為,run是當前狀態執行行為,next是指在Event參與下,幾種可能轉向的下一個狀態。
2. stateEnter和stateExit, 狀態進入和狀態退出。
如果用進入一個個房間來表示狀態流程的話, 第一種分析是隻重視著“在房間裡”和“如何轉入下一個房間”,這兩種行
為一旦確定,可以被反覆使用,進而一個流程的狀態切換可以全部表達出來。
第二中分析方法有所區別,只重視進入房間和離開房間這個兩個行為,同樣,這種模型也可以被反覆利用在其它房間,
一個流程的狀態切換也可以全部表達出來。
具體選擇取決於你的需求,比如,如果你在進入一個狀態開始,要做很多初始化工作,那麼第二種模型就很適合。
狀態變化都離不開一個主體物件,主體物件可以說包含狀態變化(行為)和狀態屬性(屬性),假設為StateOwner,
StateOwner有兩個部分組成:Task/事情和狀態。任何一個Task/事情都會對應一個狀態。
這樣,我們已經抽象出兩個主要物件:狀態State和StateOwner。
為了封裝狀態變化細節,我們可以抽象出一個狀態機StateMachine來專門實現狀態根據事情實現轉換。
這樣,客戶端外界透過狀態機可訪問狀態模式這個匣子。在實踐中,外界客戶端需要和狀態機實現資料交換,我們把
它也分為兩種:屬性和行為。
其中屬性可能需要外界告訴狀態狀態變化的主體物件Task,解決狀態的主人問題,是誰的問題;行為可能是需要持久
化當前這個主體物件的狀態到資料庫。
這兩種資料交換可以分別透過StateOwner和StateMachine與整個狀態機實現資料交換,這樣,具體狀態和狀態切換也
和外界實現瞭解耦隔離。
因此好的狀態模式實現必須有下列步驟:
(1)將每個狀態變成State的子類,實現每個狀態物件化。
(2)在每個狀態中,封裝著進入下一個狀態可能規則,這些規則是狀態變化的核心,換句話說,統一了狀態轉換的規則。
具體可採取run和next這樣的轉換行為。
下面是一個子狀態程式碼:
我個人曾經設計過一個大型遊戲系統的遊戲狀態機,遊戲狀態可以說是遊戲設計的主要架構,但是由於系統過分複雜
和時間倉促,並沒有真正實現狀態模式。
目前在實現一個電子政務專案中,需要進行流程狀態變化,在電子政務設計中,我發現,如果一開始完全按照工作流
規範開發,難度很大,它和具體專案實踐結合無法把握,而且工作流規範現在有wfmc,還有bpml,選擇也比較難。因
此,我決定走自創的中間道路。
因為,我需要做一個狀態機API,或者說狀態機框架,供具體系統呼叫:類如公文流轉應用或資訊發報送應用等。
好的狀態模式必須做到兩點:
1. 狀態變化必須從外界其它邏輯劃分出來。
2. 狀態必須可方便擴充,對其它程式碼影響非常小。
要做到這兩點,必須先明確狀態變化機制,狀態變化實際是由Event事件驅動的,可以認為是Event-condition-State,
在MVC模式一般是Event-condition-Action實現。狀態模式需要封裝的是Event-condition-State中的condition-State
部分。
清晰理解狀態和流程的關係也非常重要,因為狀態不是孤立的,可以說和流程是點和線的關係,狀態從一個方面說明
了流程,流程是隨時間而改變,狀態是擷取流程某個時間片。因此,必須明白使用狀態模式實現狀態機實際是為了更
好地表達和說明流程。
狀態和流程以及事件的關係如下:
|Event ___currentState__|______newState___ <p class="indent"> |
圖中表示了是事件改變了流程的狀態,在業務邏輯中,經常發生的是事件,如果不使用狀態模式,需要在很多業務邏
輯處實現事件到狀態判定和轉換,這有很多危險性。
最大的危險是系統沒有一個一抓就靈的主體結構,以那個遊戲系統為例,在沒有狀態模式對狀態提煉的情況下,狀態
改變由每個程式設計師想當然實現,導致每個程式設計師開發的功能在整合時就無法除錯,因為這個程式設計師可能不知道那個程
序員的程式碼在什麼執行條件下改變了遊戲狀態,結果導致自己的程式碼無法執行。
這種現象實際上拒絕了專案管理的協作性,大大地拖延專案進度(程式設計師之間要反覆商量討論對方程式碼設計)。從這
一點也說明,一個好的架構設計是一個專案快速成功完成的基礎技術保證,沒有這個技術基礎,再先進的專案管理手
段也是沒有效率的,或者是笨拙的。
狀態模式對於很多系統來說,確實是架構組成一個重要部分。
下面繼續討論如何實現一個好的狀態模式,為了實現好的狀態模式,必須在狀態模式中封裝下面兩個部分:
1. 狀態轉換規則(行為)
2. 狀態屬性(屬性)
狀態轉換行為有兩種劃分標準:
1. run和next兩個行為,run是當前狀態執行行為,next是指在Event參與下,幾種可能轉向的下一個狀態。
2. stateEnter和stateExit, 狀態進入和狀態退出。
如果用進入一個個房間來表示狀態流程的話, 第一種分析是隻重視著“在房間裡”和“如何轉入下一個房間”,這兩種行
為一旦確定,可以被反覆使用,進而一個流程的狀態切換可以全部表達出來。
第二中分析方法有所區別,只重視進入房間和離開房間這個兩個行為,同樣,這種模型也可以被反覆利用在其它房間,
一個流程的狀態切換也可以全部表達出來。
具體選擇取決於你的需求,比如,如果你在進入一個狀態開始,要做很多初始化工作,那麼第二種模型就很適合。
狀態變化都離不開一個主體物件,主體物件可以說包含狀態變化(行為)和狀態屬性(屬性),假設為StateOwner,
StateOwner有兩個部分組成:Task/事情和狀態。任何一個Task/事情都會對應一個狀態。
這樣,我們已經抽象出兩個主要物件:狀態State和StateOwner。
為了封裝狀態變化細節,我們可以抽象出一個狀態機StateMachine來專門實現狀態根據事情實現轉換。
這樣,客戶端外界透過狀態機可訪問狀態模式這個匣子。在實踐中,外界客戶端需要和狀態機實現資料交換,我們把
它也分為兩種:屬性和行為。
其中屬性可能需要外界告訴狀態狀態變化的主體物件Task,解決狀態的主人問題,是誰的問題;行為可能是需要持久
化當前這個主體物件的狀態到資料庫。
這兩種資料交換可以分別透過StateOwner和StateMachine與整個狀態機實現資料交換,這樣,具體狀態和狀態切換也
和外界實現瞭解耦隔離。
因此好的狀態模式實現必須有下列步驟:
(1)將每個狀態變成State的子類,實現每個狀態物件化。
(2)在每個狀態中,封裝著進入下一個狀態可能規則,這些規則是狀態變化的核心,換句話說,統一了狀態轉換的規則。
具體可採取run和next這樣的轉換行為。
下面是一個子狀態程式碼:
public class Running extends StateT{ // public void run(StateOwner stateOwner){ stateOwner.setCurrentState(this); } //轉換到下一個狀態的規則 //當前是Running狀態,下一個狀態可能是暫停、結束或者強制退出等 //狀態,但是絕對不會是Not_Started這樣的狀態 //轉換規則在這裡得到了體現。 public State next(Event e) { if(transitions == null){ addEventState(new EventImp("PAUSE"), new Suspended()); addEventState(new EventImp("END"), new Completed()); addEventState(new EventImp("STOP"), new Aborted()); } return super.next(e); } } 外界直接呼叫 StateMachine的關鍵方法transition;實行狀態的自動轉變。 public class StateMachine { /** * 狀態切換 * 根據Event引數,執行相應的狀態。 * 1. 獲得當前狀態 * 2. 使用當前狀態的next()轉換 * |Event * ___currentState__|______newState___ * * @param inputs */ public final void transition(String taskid, Event e) throws Exception { State currentState = readCurrentState(taskid); //從資料庫獲得當前狀態 StateOwner stateOwner = new StateOwner(taskid, currentState); //轉換狀態 currentState = currentState.next(e); if (currentState != null) { currentState.run(stateOwner); saveCurrentState(stateOwner); //儲存當前狀態 } } } |
相關文章
- 狀態機工作流
- 【架構設計】無狀態狀態機在程式碼中的實踐架構
- Squirrel狀態機-從原理探究到最佳實踐UI
- 工作流從無狀態切換到有狀態的好處
- 狀態模式模式
- Flutter 狀態管理實踐Flutter
- 在 .NET 中使用有限狀態機實現工作流建模 - Lloyd
- React 路由狀態管理總結React路由
- 【iCore4 雙核心板_FPGA】例程七:狀態機實驗——狀態機使用FPGA
- 【iCore3 雙核心板_FPGA】例程九:狀態機實驗——狀態機使用FPGA
- 從狀態模式看 JavaScript 與 Java模式JavaScript
- JavaStatePattern(狀態模式)JavaAST模式
- JS 狀態模式JS模式
- (三)狀態模式模式
- 狀態模式(State)模式
- 狀態機
- 前端狀態管理與有限狀態機前端
- 狀態機模式 與 ajax 的結合運用模式
- 狀態模式(c++實現)模式C++
- 【iCore1S 雙核心板_FPGA】例程六:狀態機實驗——狀態機使用FPGA
- RocketMQ 5.0:無狀態代理模式的探索與實踐MQ模式
- Flutter狀態管理 - 初探與總結Flutter
- Http協議狀態碼總結HTTP協議
- 《JavaScript設計模式與開發實踐》模式篇(13)—— 狀態模式JavaScript設計模式
- 掌握 Nuxt 3 中的狀態管理:實踐指南UX
- 設計模式-狀態模式設計模式
- 設計模式:狀態模式設計模式
- 從Promise的實現來看有限狀態機Promise
- 狀態變化模式模式
- 狀態模式(State pattern)模式
- 17_狀態模式模式
- 有限狀態機(FSM)的使用
- 用設計模式去掉沒必要的狀態變數 —— 狀態模式設計模式變數
- 使用列舉實現狀態機來優雅你的狀態變更邏輯
- 行為型模式:狀態模式模式
- 設計模式(十五)狀態模式設計模式
- 設計模式之——狀態模式設計模式
- javascript設計模式狀態模式JavaScript設計模式