1.背景介紹
什么是有限狀態(tài)機(jī)?
有限狀態(tài)機(jī)(Finite-state machine)是一個(gè)非常有用的模型鬓催,可以模擬世界上大部分事物肺素。它 是一個(gè)數(shù)學(xué)模型。是一個(gè)抽象機(jī)器宇驾,在任何時(shí)候都可以處于有限數(shù)量的狀態(tài)之一倍靡。響應(yīng)某些外部輸入, FSM可以從一個(gè)狀態(tài)轉(zhuǎn)換到另一個(gè)狀態(tài); 從一種狀態(tài)到另一種狀態(tài)的變化稱為過(guò)渡课舍。 狀態(tài)機(jī)的行為可以在現(xiàn)代社會(huì)中的許多設(shè)備中觀察到塌西,這些設(shè)備根據(jù)它們呈現(xiàn)的事件序列執(zhí)行預(yù)定的一系列行為。 例如自動(dòng)售貨機(jī)筝尾,當(dāng)存放適當(dāng)?shù)挠矌沤M合時(shí)分配產(chǎn)品捡需,當(dāng)車輛等待時(shí)改變順序的交通燈等。
在我們前端開發(fā)中筹淫,我們可以套用有限狀態(tài)機(jī)模型站辉,將業(yè)務(wù)流程狀態(tài)化,劃分狀態(tài)和相應(yīng)的觸發(fā)事件與動(dòng)作,利用生命周期事件進(jìn)行控制與執(zhí)行
2.知識(shí)剖析
有限狀態(tài)機(jī)一般都有以下特點(diǎn):?
(1)可以用狀態(tài)來(lái)描述事物饰剥,并且任一時(shí)刻殊霞,事物總是處于一種狀態(tài);
(2)事物擁有的狀態(tài)總數(shù)是有限的汰蓉;
(3)通過(guò)觸發(fā)事物的某些行為绷蹲,可以導(dǎo)致事物從一種狀態(tài)過(guò)渡到另一種狀態(tài);
(4)事物狀態(tài)變化是有規(guī)則的古沥,A狀態(tài)可以變換到B瘸右,B可以變換到C,A卻不一定能變換到C岩齿;
(5)同一種行為,可以將事物從多種狀態(tài)變成同種狀態(tài)苞俘,但是不能從同種狀態(tài)變成多種狀態(tài)盹沈。
狀態(tài)機(jī)由一組狀態(tài)和轉(zhuǎn)換組成:?
狀態(tài) : 固體 、 液體 吃谣、 氣體乞封。?
轉(zhuǎn)換 :融化 、汽化 岗憋、 冷凝 肃晚、 凍結(jié)。?
以上的形式可以狀態(tài)機(jī)來(lái)寫一下
首先需要引入有限狀態(tài)機(jī)庫(kù)?狀態(tài)機(jī)庫(kù)
以上的形式可以狀態(tài)機(jī)來(lái)寫一下
首先需要引入有限狀態(tài)機(jī)庫(kù)?狀態(tài)機(jī)庫(kù)
var fsm = new StateMachine({
? ? ? ? ? ? ? ? init: 'solid',
? ? ? ? ? ? ? ? transitions: [
? ? ? ? ? ? ? ? ? { name: 'melt',? ? from: 'solid',? to: 'liquid' },
? ? ? ? ? ? ? ? ? { name: 'freeze',? from: 'liquid', to: 'solid'? },
? ? ? ? ? ? ? ? ? { name: 'vaporize', from: 'liquid', to: 'gas'? ? },
? ? ? ? ? ? ? ? ? { name: 'condense', from: 'gas',? ? to: 'liquid' }
? ? ? ? ? ? ? ? ],
? ? ? ? ? ? ? ? methods: {
? ? ? ? ? ? ? ? ? onMelt:? ? function(){ console.log('I melted')? ? },
? ? ? ? ? ? ? ? ? onFreeze:? function(){ console.log('I froze')? ? },
? ? ? ? ? ? ? ? ? onVaporize: function(){ console.log('I vaporized') },
? ? ? ? ? ? ? ? ? onCondense: function(){ console.log('I condensed') }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? ? ? ? ? //方法調(diào)用? ? ? ? ? ? ? ? ? ? ? ? //1仔戈,自執(zhí)行方法:? ? ? ? ? ? ? ? ? ? ? ? fsm.onMelt();
? ? ? ? ? ? ? ? ? ? ? ? fsm.onFreeze();
? ? ? ? ? ? ? ? ? ? ? ? fsm.onVaporize();
? ? ? ? ? ? ? ? ? ? ? ? fsm.onCondense();
? ? ? ? ? ? ? ? ? ? ? ? //1关串、觸發(fā)調(diào)用方式:? ? ? ? ? ? ? ? ? ? ? ? fsm.Melt();
? ? ? ? ? ? ? ? ? ? ? ? fsm.Freeze();
? ? ? ? ? ? ? ? ? ? ? ? fsm.Vaporize();
? ? ? ? ? ? ? ? ? ? ? ? fsm.Condense();
init選項(xiàng)用來(lái)表示fsm對(duì)象的初始狀態(tài),?
transitions選項(xiàng)用來(lái)描述fsm對(duì)象所有狀態(tài)的變化規(guī)則监徘,每一種變化規(guī)則對(duì)應(yīng)一種行為晋修。?
methods方法為實(shí)例的每一種行為都添加了一個(gè)方法,調(diào)用這個(gè)方法就相當(dāng)于觸發(fā)對(duì)象的某種行為凰盔,當(dāng)對(duì)象行為發(fā)生時(shí)墓卦,對(duì)象的狀態(tài)就可以發(fā)生變化。如以上例子創(chuàng)建的實(shí)例將擁有如下行為方法:?
fsm.Melt() : 調(diào)用該方法户敬,實(shí)例狀態(tài)將從'solid'變?yōu)?liquid'?
fsm.Freeze() : 調(diào)用該方法落剪,實(shí)例狀態(tài)將從'liquid'變?yōu)?solid'?
fsm.Vaporize() : 調(diào)用該方法,實(shí)例狀態(tài)將從'liquid'變?yōu)?gas'?
fsm.Condense() : 調(diào)用該方法尿庐,實(shí)例狀態(tài)將從'gas'變?yōu)?liquid'
Javascript Finite State Machine允許為每個(gè)事件指定兩個(gè)自定義方法忠怖,以Melt事件為例:?
onbeforeMelt:在Melt事件發(fā)生之前觸發(fā)?
onafterMelt :在Melt事件發(fā)生之后觸發(fā)。?
每個(gè)狀態(tài)指定兩個(gè)自定義方法屁倔,以solid狀態(tài)為例:?
onleaveSolid :在離開solid狀態(tài)時(shí)觸發(fā)?
onenterLiquid :在進(jìn)入liquid狀態(tài)時(shí)觸發(fā)脑又。
輔助方法:?
// fsm.is(s) - 如果狀態(tài)s是當(dāng)前狀態(tài),則返回true?
// fsm.can(t) - 如果t從當(dāng)前狀態(tài)發(fā)生轉(zhuǎn)換,則返回true?
// fsm.cannot(t) - 如果t從當(dāng)前狀態(tài)不能發(fā)生轉(zhuǎn)換问麸,則返回true
// fsm.transitions() - 返回當(dāng)前狀態(tài)允許的轉(zhuǎn)換列表?
// fsm.allTransitions() - 返回所有可能的轉(zhuǎn)換的列表?
// fsm.allStates() - 返回所有可能狀態(tài)的列表?
//Cancelling a Transition 取消轉(zhuǎn)換?
3.常見(jiàn)問(wèn)題
有限狀態(tài)機(jī)有哪些應(yīng)用場(chǎng)景往衷?
4.解決方案
滿足3點(diǎn)即可用:所需狀態(tài)確定,有事件觸發(fā)轉(zhuǎn)變狀態(tài)严卖,總狀態(tài)有限且轉(zhuǎn)變有規(guī)律席舍。
頁(yè)面可用有限狀態(tài)機(jī)的元素較多且有規(guī)律時(shí)可用:例如:開關(guān)按鈕,下拉菜單哮笆,
還有任務(wù)中殺人游戲的玩家死活狀態(tài)来颤、白天黑夜?fàn)顟B(tài)等,這里實(shí)現(xiàn)的是流程控制
5.編碼實(shí)戰(zhàn)
6.擴(kuò)展思考
有限狀態(tài)機(jī)有哪些優(yōu)點(diǎn)稠肘?
有限狀態(tài)機(jī)的寫法福铅,邏輯清晰,表達(dá)力強(qiáng)项阴,有利于封裝事件滑黔。一個(gè)對(duì)象的狀態(tài)越多、發(fā)生的事件越多环揽,就越適合采用有限狀態(tài)機(jī)的寫法略荡。 另外,JavaScript語(yǔ)言是一種異步操作特別多的語(yǔ)言歉胶,常用的解決方法是指定回調(diào)函數(shù)汛兜, 但這樣會(huì)造成代碼結(jié)構(gòu)混亂、難以測(cè)試和除錯(cuò)等問(wèn)題通今。有限狀態(tài)機(jī)提供了更好的辦法: 把異步操作與對(duì)象的狀態(tài)改變掛鉤粥谬,當(dāng)異步操作結(jié)束的時(shí)候,發(fā)生相應(yīng)的狀態(tài)改變衡创,由此再觸發(fā)其他操作帝嗡。 這要比回調(diào)函數(shù)、事件監(jiān)聽璃氢、發(fā)布/訂閱等解決方案哟玷,在邏輯上更合理,更易于降低代碼的復(fù)雜度一也。
7.參考文獻(xiàn)
8.更多討論
控制天數(shù)變化巢寡,該如何實(shí)現(xiàn)
創(chuàng)建一個(gè)控制天數(shù)的參數(shù)
? ? var day=new StateMachine({
? ? ? ? init:'1',
? ? ? ? transitions:[{
? ? ? ? ? ? name:'add',
? ? ? ? ? ? from:'1',
? ? ? ? ? ? to:'1++'
? ? ? ? },
? ? ? ? {
? ? ? ? ? ? name:'over',
? ? ? ? ? ? from:'1++',
? ? ? ? ? ? to:'1'
? ? ? ? }
? ? ? ? ],
? ? ? ? methods:{
? ? ? ? ? ? onAdd:function(){
? ? ? ? ? ? }
? ? ? ? }
? ? })