Go入門學習實例——有限狀態機

安裝好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檔 ] 變成 [ 關閉 ]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章