傳統的有限狀態機理論只是根基,現在很少真正把它應用到我們的項目中,它已經不足以應對我們如今在嵌入式系統的軟件設計中遇到的問題了。
那么啥是HSM? 大牛是這么講的,說實話有點難懂,我從入門到放棄到再入門了好幾遍,我不打算對這些概念做什么解釋,假如有一天你覺得你的理論不夠用了再回去翻可能效果更好,或者你聽我扯完蛋,再去看發現也不是那么難懂,我就滿足了。
我的理解:HSM就是一個狀態機包含子狀態機,從而形成的層次結構,這不就是面向對象理論和有限狀態機理論結合的產物?對的,這年頭,你搞嵌入式軟件設計,要是沒點面向對象的思想在里面,出門都不好意思和同行打招呼(他有女朋友,我有對象~?。?/p>
對比一下傳統的FSM狀態機,可能更好懂一些,(請忽略內部那些e/x后面再說)如下:
為什么要引入層次式狀態機,這種嵌套的結構明顯會將事情搞復雜。
層次式狀態機的設計和實現說實話灰常復雜,你要是沒學好數據結構和算法,就不要去看他的源碼了,挫敗感瞬間會涌上心頭。那么為啥還要用呢,設計層次式狀態機是復雜,但是應用起來并不復雜,沒有啥比調用函數API解決問題更簡單的方式了,而很有意思的是,應用它你的應用會變得無比清晰和簡明。
軟件界中,最糟糕的設計之一,重復造輪技術,因為隨著需求的爆發,它最終會演變成你我都看不懂的存在(哪怕你用作文寫注釋)。
我們由一個現實的問題,來切入到從傳統的有限狀態機(FSM)切換到層次狀態機(HSM)所帶來的好處舉一個空調的運行控制的例子吧,空調大家都熟悉,內部四大件:壓縮機 四通閥 冷凝器(帶風扇)蒸發器(帶風扇)。
當你從關機狀態到制冷模式和制熱模式兩種狀態,其實兩個風機都要開,壓機也都要開,區別在于四通閥的方向不一樣。
傳統FSM: 關機狀態, 制冷狀態,制熱狀態等三個狀態。在制冷制熱狀態都要開風機和壓機,代碼里面你要寫兩遍(再現重復造輪技術)。
進階HSM: 關機狀態,運行狀態,運行子狀態:制冷,運行子狀態:制熱,開風機和壓機的操作扔進運行狀態處理(也叫超狀態,可以類比) ,這樣代碼中寫一遍就可以(復用的藝術)。
這里應用到了面向對象的核心之一,繼承思想來實現復用,在軟件設計中,沒有比這更實用的技術。
既然提到了面向對象,提一下三大核心概念,封裝繼承和多態,上面應用的就是繼承思想,在事件驅動型系統中,我們叫行為繼承,接下來介紹那兩大概念。
封裝技術是基于抽象而來的,抽象抽象是抽成一頭象,不是真讓你去抽象(可能有繩命危險),他的作用主要是,能讓你縮放自如,代碼界大牛總是能以難以想象的速度定位bug,增加需求等其實用的就是縮放技術(并不是他的腦回路連接方式和我們的不同)。
運用這個技術可以讓你以各種方式把大象放進冰箱,是開/關門一頭放,還是切了放,完全取決于你是不是認為他是一頭象。這么說有點抽象,具體點,你去四兒子店告訴銷售,你要買輛車,他會立即向你介紹各種車型,假如你說我要四個輪子,一個發動機,一個變速箱,一個車殼,加一個底盤等等。他可能會懷疑人生。
多態對應我們的狀態機就更好理解了,例如制冷狀態 制熱都是針對運行狀態的多種狀態的擴展,基于同一個超狀態擴展多個子狀態。
到這里關于層次式狀態機是個啥,他為何而來,他到底怎么來的 ,你可能腦子里有個大體的印象了。這里層次式狀態機雖然是基于面向對象技術而產生,但是他不等于面向對象編程,和我們傳統的對象和類的概念還是不小的區別,實踐中慢慢體會吧 。
經典狀態機分兩種:Mealy 機和 Moore機。
簡單介紹:Mealy 機 沒有進入動作和退出動作,只有狀態和轉換動作。
Moore 機 有進入動作和退出動作,沒有轉換動作。
這里不打算分開講了,UML對經典狀態機進行了擴展,合二為一,也就是一個狀態機有:狀態,進入動作,退出動作,轉換動作組成。關于啥是UML(這個叫做統一建模語言,我建議你不要去看,這顆思想的種子需要挖一個好大的坑,容易閃腰)。
看到這里,你應該知道什么是層次式狀態機了,也知道了怎么構造他,但這還不夠,下面還有個大活,就是層次式狀態機是如何轉換的,說實話我看完原著沒怎么懂,只有自己真的上機執行 和操作過了以后,算是基本搞明白了,所以這里,我不打算展開去講理論如何轉換的,書里講的比我專業很多。
我想告訴大家基于層次式狀態機設計的幾個屬性,記住他們,你就可以直接上例子,我們再例子里面慢慢聊了。
劃重點:一、狀態機可以分層次,但是系統停留階段只能是最終的子狀態,他不能停留在任何層次的超狀態,這個停留的狀態稱為活動狀態。例如上面空調的例子,運行狀態無法停留,他是一個過渡狀態,執行他是有意義的,但停留沒有意義,最終活動狀態要么制冷要么制熱狀態。
劃重點:二、狀態機本身是不會有任何動作的,只有觸發相關事件,他才會執行程序上下文,每個事件會有對應的動作范型,這里講一下一個狀態機必備的事件-動作范型。
初始事件-動作范型:也就是狀態機在初始化過程中需要執行的程序上下文。
進入事件-動作范型:切換狀態機時,目標狀態機必須執行的程序上下文。
退出事件-動作范型:切換狀態機時,源狀態機必須執行的程序上下文。
轉換事件-動作范型:切換狀態機時,先于進入/退出動作執行的程序上下文。
層次式狀態機的內部實現復雜,應用只是看著復雜,當你真正理解以后,會覺得無比清晰和簡單。下一屆講大活,層次式狀態機的轉換執行的順序和動作集,下期再見~!