根據需求畫出狀態圖後
接著我們便來思考如何實作,
(1). 有初始狀態:所以我們需要有個變數( state )來儲存狀態,而且這個狀態的初始值就是初始狀態
(2). 一系列的狀態們:狀態改變時,也應該被儲存起來( state )
(3). 事件、轉移:當某個狀態 + 某個事件會導致狀態的轉移,nextState = transition(previusState, event)
,所以要實作一個 function transition,這個 function 裡應該會有個 mapping ,記錄著什麼狀態 + 什麼事件可以轉移狀態。
const initialState = "站姿、靜止"
關於這個 transition ,首先會想到 input 進去,為了辨識什麼 state, event 來決定要回傳什麼,執行辨識的底層實作一定會經歷許多邏輯判斷,才會回傳對應的結果給我們。假設狀態會有許多個,如果不想大量使用 if/else
,此時我們想到可以使用 switch/case
const initialState = "站姿、靜止"
// 3 實作 transition
function transition (state) {
switch(state){
case "站姿、靜止": // 3.1 - 過濾狀態
// 3.2 - 回傳經過轉移後的狀態 (回傳 nextState )
return "站姿、移動"
case "站姿、移動":
return "站姿、靜止"
case "跳躍中":
return "站姿、移動"
case "俯臥、靜止":
case "俯臥、移動":
default:
throw "The state is not existed, machine broken"
}
}
上面的實作中,我們已經能在第一個 switch case 辨識 state ,那促使 state 轉移的是什麼呢? 是事件 event,而 transition 則是根據對應的 state 及對應的 event 發生時,改變 state,所以我們接著需要在 state 底下來辨識 event ,才能達到我們說的 某個狀態 + 某個事件會導致狀態的轉移,nextState = transition(previusState, event)
function transition (state,event) {
switch(state){
case "站姿、靜止":
switch(event){
case "跳躍":
// 3.2 - 回傳經過轉移後的狀態 (回傳 nextState )
return "跳躍中"
case "開始移動":
return "站姿、移動"
case "臥倒":
return "俯臥、靜止"
default:
// 如果 "站姿、靜止" 狀態,遇到 "跳躍","開始移動","臥倒" 以外的事件
// 不轉移狀態
return state
}
case "站姿、移動":
switch(event){
case "停止移動":
return "站姿、靜止"
default:
// 如果 "站姿、移動" 狀態,遇到 "停止移動" 以外的事件
// 不轉移狀態
return state
}
case "跳躍中":
switch(event){
case "降落":
return "站姿、靜止"
default:
// 如果 "跳躍中" 狀態,遇到 "降落" 以外的事件
// 不轉移狀態
return state
}
case "俯臥,靜止": // 應該是 "俯臥、靜止" 沒用常數保護的話,打錯就出現 bug 了
switch(event){
case "起身":
return "站姿、靜止"
case "開始移動":
return "俯臥、移動"
default:
// 如果 "俯臥、靜止" 狀態,遇到 "起身", "開始移動" 以外的事件
// 不轉移狀態
return state
}
case "俯臥、移動":
switch(event){
case "停止移動":
return "俯臥、靜止"
default:
// 如果 "俯臥、移動" 狀態,遇到 "停止移動” 以外的事件
// 不轉移狀態
return state
}
default:
throw "The state is not existed, machine broken"
}
}
const initialState = "站姿、靜止"
function transition (state,event) {
// ...
}
const nextState = transition(initialState,"") // "站姿、靜止"
const nextState2 = transition(initialState,"開始移動") // "站姿、移動"
const nextState3 = transition(nextState2,"停止移動") // "站姿、靜止"
const nextState4 = transition(nextState3,"臥倒") // "臥倒、靜止"
如此我們便可以根據對應的 state 及 event 來決定要不要進行 transition 了,也算是初步完成我們的 state machine 了。我們來回顧一下現在還缺什麼
明天讓我們根據以上不足之處,繼續完備一個 State Machine