夏京川,段從武,宋國堃,趙世平
(四川大學 制造科學與工程學院,四川 成都 610065)
在某試驗臺測控系統(tǒng)中,根據(jù)試驗要求,存在多個中間狀態(tài)并且相互之間有復雜的轉(zhuǎn)換關系,確定不同輸入條件下測控系統(tǒng)狀態(tài)遷移過程以及內(nèi)部切換模式,是設計該系統(tǒng)軟件的關鍵。本文根據(jù)FSM原理,對系統(tǒng)中對象的控制和順序視圖進行了建模,并且采用State模式,將狀態(tài)轉(zhuǎn)換顯示化,與不同狀態(tài)的行為進行隔離,極大地提高了軟件設計的可靠性與復用性。
FSM(finitestatemachine)是包含有限狀態(tài)的概念化機器,狀態(tài)機在某一個時刻只有一個狀態(tài),通常由輸入事件引起狀態(tài)的改變,而下一個狀態(tài)則依賴于當前狀態(tài)和輸入事件[1]。其中,狀態(tài)表示一種可識別、存在于一段時間間隔內(nèi)的情況;事件是在某一個時間點發(fā)生的事情,具有原子性且在概念上無持續(xù);動作是與狀態(tài)轉(zhuǎn)換相關的可選輸出,動作執(zhí)行計算,作為狀態(tài)轉(zhuǎn)換的結(jié)果;警戒條件是值為真或假的布爾表達式,可以對事件進行驗證[2]。一個典型的微波爐有限狀態(tài)機系統(tǒng)如圖1所示[3]。
圖1 微波爐系統(tǒng)FSMUML圖示例
簡單的FSM可以使用switch/case語句來實現(xiàn),然而此時FSM的邏輯和實現(xiàn)動作的代碼之間沒有分離,難以達到代碼的復用和有效維護。狀態(tài)遷移表是實現(xiàn)FSM的另一種途徑,通過一個處理事件的引擎,查找與事件匹配的轉(zhuǎn)換,調(diào)用相應的動作,并更改狀態(tài)[4]。但對于大型FSM,狀態(tài)遷移表的查找會耗費大量時間,導致效率低下。使用State模式,能夠既具有嵌套switch/case語句的效率又具有解釋遷移表的靈活性。
State模式允許對象在內(nèi)部狀態(tài)改變時改變其行為,此時對象對外表現(xiàn)為類已經(jīng)被修改[5]。State模式參與者通常包括Context(環(huán)境),定義客戶感興趣的接口,提供對外表現(xiàn)的事件,并維護一個ConcreteState的實例以定義當前狀態(tài);IState(狀態(tài)抽象接口),用以封裝與Context特定狀態(tài)相關的行為;ConcreteState(具體狀態(tài)子類),實現(xiàn)一個與Context的一個狀態(tài)相關的行為[6]。
其中,Context將與狀態(tài)相關的請求委托給Concrete對象處理,并可將自身作為參數(shù)傳遞給狀態(tài)對象。Context或ConcreteState子類都可決定當前狀態(tài)的后繼者以及在何種條件下進行狀態(tài)轉(zhuǎn)換。
在某試驗臺測控系統(tǒng)中,其上鎖試驗狀態(tài)圖如圖2所示。
圖2 上鎖試驗狀態(tài)圖
根據(jù)系統(tǒng)要求,試驗的開始狀態(tài)為零位,最終狀態(tài)回到零位或處于出錯狀態(tài)。試驗被設置為自動進行,因而對外的接口表現(xiàn)均為Auto事件。在狀態(tài)的切換中,會根據(jù)前一個狀態(tài)與目標狀態(tài)而執(zhí)行相應動作;在某些狀態(tài)遷移間,還涉及條件的判斷,通常條件不滿足直接進入出錯狀態(tài)。
根據(jù)試驗的狀態(tài)圖,可創(chuàng)建其狀態(tài)模式的UML表示,如圖3所示。
圖3 上鎖實驗State模式類圖
其中,ExperimentContext繼承IAction接口,并實現(xiàn)其中定義的動作;同時,其關聯(lián)一個IMachineState對象,以標識當前的狀態(tài)并指明將執(zhí)行的操作;具體的狀態(tài)繼承于IMachineState接口,持有回指向上下文類的引用,以調(diào)用實現(xiàn)于IAction的動作,并決定狀態(tài)的后繼者。
通過狀態(tài)模式的使用,將FSM中的動作、事件與狀態(tài)分離開來,狀態(tài)被封裝為單獨的類,以便不同的實驗對相同的狀態(tài)進行復用,也減少了增加、刪除狀態(tài)以及切換狀態(tài)模式的復雜性。
在試驗臺系統(tǒng)中,不同的試驗模式通常是在基本試驗的基礎上,添加相應的行為以及狀態(tài),此時已存在的狀態(tài)無需改變,可以有效地復用。
在加載試驗中,需要在上鎖保持狀態(tài)加載至一定的力,并保持一段時間。如圖4所示,此時只需要將上鎖保持狀態(tài)的后繼者指向加載狀態(tài),并創(chuàng)建加載、加載保持狀態(tài),已經(jīng)存在的狀態(tài)不需改變,并且基本試驗的邏輯不用更改。
此外,仍需要添加屬于加載試驗特定的動作、條件以及狀態(tài)切換:
public class LoadContext:ExperimentContext, ILoadingAction//繼承ILoadingAction,以實現(xiàn)要求的動作{
public override void SetMachineState(ExpState state){
base.SetMachineState(state);
if(state==ExpState.StateLockedHolding)
圖4 加載試驗狀態(tài)圖
SetMachineState(ExpState.StateLoading); //截斷某個狀態(tài),并重新指定后繼者
if(state==ExpState.StateLoading) ...
if(state==ExpState.StateLoadKeeping) ...
}
public async Task
public void LockLoadingAction(){...}
public async Task LoadingKeepingAction(){...}//實現(xiàn)相應的條件與動作
}
對于自動試驗,F(xiàn)SM的最終狀態(tài)必然為零位或者出錯,同時對外表現(xiàn)事件只有AutoStartEvent。而對于某些試驗模式,通常還需要人工的干預,此時可提供額外的手動事件,并攔截某一試驗狀態(tài):
public void Task AutoStartEvent(ExpState? interrupt=null){
while(CurrentState!=ExpState.OriginalPos&&CurrentState!=ExpState.Error){
if(interrupt!=null&&CurrentState==interrupt.Value) break;//在指定的攔截狀態(tài)停止自動執(zhí)行
State.ToNextState(this);
}
}
在開鎖試驗中,卸載壓力與加載壓力的工作需要由人工進行,應用程序可為操作者提供ManualUnLoadEvent與MannualLoadEvent,并提供AutoEndEvent事件(圖5),以便于操作者選擇在某一時刻回到自動試驗,完成其他操作。
圖5 開鎖試驗狀態(tài)圖
同樣,對應于開鎖試驗,需要添加試驗相關特定的動作、條件與切換邏輯,而這些并沒有改變基本試驗的業(yè)務邏輯,卻能夠復用已存在的狀態(tài),極大地提高了應用程序的可維護性與可擴展性。
FSM是一種對系統(tǒng)或?qū)ο蟮目刂坪晚樞蛞晥D進行建模的重要工具。采用FSM實現(xiàn)試驗臺測控系統(tǒng),能夠簡化應用程序的邏輯,更清晰地理解系統(tǒng)的復雜性,并提高了實時控制的可靠性、準確性。而采取State模式來實現(xiàn)FSM,最大化分隔其邏輯與動作實現(xiàn),提升了程序代碼的復用性,為構(gòu)建可維護、可擴展測控系統(tǒng)軟件奠定了基礎。