安裝好IDEA和GO插件,創建項目GoDemo
鍵入代碼:
FSM.go
package src
import (
"fmt"
"sync"
)
type FSMState string //狀態
type FSMEvent string //事件
type FSMHandler func() FSMState //處理方法,並返回新的狀態
//有限狀態機
type FSM struct {
mu sync.Mutex //排它鎖
state FSMState //當前狀態
handlers map[FSMState]map[FSMEvent]FSMHandler //處理地圖集,每一個狀態都可以出發有限個事件,執行有限個處理
}
//獲取當前狀態
func (f *FSM) getState() FSMState {
return f.state
}
//設置當前狀態
func (f *FSM) setState(newState FSMState) {
f.state = newState
}
//某狀態添加事件處理方式
func (f *FSM) AddHandler(state FSMState, event FSMEvent, handler FSMHandler) *FSM {
if _, ok := f.handlers[state]; !ok {
f.handlers[state] = make(map[FSMEvent]FSMHandler)
}
if _, ok := f.handlers[state][event]; ok {
fmt.Print("[警告] 狀態(%s)事件(%s)已定義過", state, event)
}
f.handlers[state][event] = handler
return f
}
//事件處理
func (f *FSM) Call(event FSMEvent) FSMState {
f.mu.Lock()
defer f.mu.Unlock()
events := f.handlers[f.getState()]
if events == nil {
return f.getState()
}
if fn,ok := events[event]; ok {
oldState := f.getState()
f.setState(fn())
newState := f.getState()
fmt.Println("狀態從 [", oldState,"] 變成 [", newState, "]")
}
return f.getState()
}
//實例化FSM
func NewFSM(initState FSMState) *FSM {
return &FSM{
state: initState,
handlers: make(map[FSMState]map[FSMEvent]FSMHandler),
}
}
FSM_demo.go
package main
import (
"fmt"
. "./src"
)
var (
//
PowerOff = FSMState("關閉")
FirstGear = FSMState("1檔")
SecondGear = FSMState("2檔")
ThirdGear = FSMState("3檔")
//
PowerOffEvent = FSMEvent("按下關閉按鈕")
FirstGearEvent = FSMEvent("按下1檔按鈕")
SecondGearEvent = FSMEvent("按下2檔按鈕")
ThirdGearEvent = FSMEvent("按下3檔按鈕")
//
PowerOffHandler = FSMHandler(func() FSMState {
fmt.Println("電風扇已關閉")
return PowerOff
})
FirstGearHandler = FSMHandler(func() FSMState {
fmt.Println("電風扇開啓1檔,微風徐來!")
return FirstGear
})
SecondGearHandler = FSMHandler(func() FSMState {
fmt.Println("電風扇開啓2檔,涼颼颼!")
return SecondGear
})
ThirdGearHandler = FSMHandler(func() FSMState {
fmt.Println("電風扇開啓3檔,髮型被吹亂了!")
return ThirdGear
})
)
//電風扇
type ElectricFan struct {
*FSM
}
//實例化電風扇
func NewElectricFan(initState FSMState) *ElectricFan {
return &ElectricFan{
FSM: NewFSM(initState),
}
}
//入口函數
func main() {
//電風扇實例
efan := NewElectricFan(PowerOff)
//關閉狀態
efan.AddHandler(PowerOff, PowerOffEvent, PowerOffHandler)
efan.AddHandler(PowerOff, FirstGearEvent, FirstGearHandler)
efan.AddHandler(PowerOff, SecondGearEvent, SecondGearHandler)
efan.AddHandler(PowerOff, ThirdGearEvent, ThirdGearHandler)
//1檔狀態
efan.AddHandler(FirstGear, PowerOffEvent, PowerOffHandler)
efan.AddHandler(FirstGear, FirstGearEvent, FirstGearHandler)
efan.AddHandler(FirstGear, SecondGearEvent, SecondGearHandler)
efan.AddHandler(FirstGear, ThirdGearEvent, ThirdGearHandler)
//2檔狀態
efan.AddHandler(SecondGear, PowerOffEvent, PowerOffHandler)
efan.AddHandler(SecondGear, FirstGearEvent, FirstGearHandler)
efan.AddHandler(SecondGear, SecondGearEvent, SecondGearHandler)
efan.AddHandler(SecondGear, ThirdGearEvent, ThirdGearHandler)
//3檔狀態
efan.AddHandler(ThirdGear, PowerOffEvent, PowerOffHandler)
efan.AddHandler(ThirdGear, FirstGearEvent, FirstGearHandler)
efan.AddHandler(ThirdGear, SecondGearEvent, SecondGearHandler)
efan.AddHandler(ThirdGear, ThirdGearEvent, ThirdGearHandler)
//開始測試狀態變化
efan.Call(ThirdGearEvent);
efan.Call(FirstGearEvent);
efan.Call(PowerOffEvent);
efan.Call(SecondGearEvent);
efan.Call(PowerOffEvent);
}
運行結果:
D:\AI\IntelliJ-IDEA\bin\runnerw.exe D:\AI\Go\bin\go.exe run E:/各種語言/Go/projects/GoDemo/FSM_demo.go
電風扇開啓3檔,髮型被吹亂了!
狀態從 [ 關閉 ] 變成 [ 3檔 ]
電風扇開啓1檔,微風徐來!
狀態從 [ 3檔 ] 變成 [ 1檔 ]
電風扇已關閉
狀態從 [ 1檔 ] 變成 [ 關閉 ]
電風扇開啓2檔,涼颼颼!
狀態從 [ 關閉 ] 變成 [ 2檔 ]
電風扇已關閉
狀態從 [ 2檔 ] 變成 [ 關閉 ]