參考文檔:
https://www.cnblogs.com/double12gzh/p/13621445.html
有限狀態(tài)機(jī)(FSM)是一個抽象的機(jī)器纹烹,任何時刻該機(jī)器都處于某個狀態(tài),且狀態(tài)總數(shù)有限钦无。該機(jī)器可以根據(jù)輸入晒衩,從一個狀態(tài)轉(zhuǎn)換到另一個狀態(tài)中歹颓。
三個關(guān)鍵要素:初始狀態(tài),可能狀態(tài)列表番官,觸發(fā)狀態(tài)變化的輸入
第一種實(shí)現(xiàn)思路
package main
import(
"bufio"
"fmt"
"log"
"os"
"strings"
)
type State uint32
const (
Locked State = iota
Unlocked
)
const (
dzToubi = "coin"
dzTuiGan = "push"
)
func main() {
state := Locked //初始狀態(tài),鎖定
prompt(state)
reader := bufio.NewReader(os.Stdin)
for {
cmd, err := reader.ReadString('\n')
if err != nil {
log.Fatalln(err)
}
cmd = strings.TrimSpace(cmd)
switch state {
case Locked:
if cmd == dzToubi {
fmt.Println("解鎖,請通行")
state = Unlocked
} else if cmd == dzTuiGan {
fmt.Println("禁止通行裆蒸,請先解鎖")
} else {
fmt.Println("無效命令,請重新輸入")
}
case Unlocked:
if cmd == dzToubi {
fmt.Println("門已開蚂四,投幣算是慈善了")
} else if cmd == dzTuiGan {
fmt.Println("請通行光戈,隨后道閘關(guān)閉")
state = Locked
} else {
fmt.Println("無效命令哪痰,請重新輸入")
}
}
}
}
func prompt(s State) {
m := map[State]string {
Locked: "關(guān)閉",
Unlocked: "開通",
}
fmt.Printf("當(dāng)前閘機(jī)狀態(tài)為:[%s]遂赠,你下一步的動作是:[ coin | push ]\n", m[s])
}
優(yōu)化后的解法
package main
import(
"bufio"
"fmt"
"log"
"os"
"strings"
)
type State uint32
const (
Locked State = iota
Unlocked
)
const (
CmdCoin = "coin"
CmdPush = "push"
)
type Turnstile struct {
s State
}
func (p *Turnstile) ExecuteCmd( cmd string ) {
//以當(dāng)前狀態(tài)和收到的命令構(gòu)成一個二元組
tupple := StateCmdTupple{p.s, strings.TrimSpace(cmd)}
//通過二元組查詢狀態(tài)轉(zhuǎn)換表,獲得一個轉(zhuǎn)換函數(shù)
//本例中晌杰,這個表是通過map實(shí)現(xiàn)的跷睦,二元組是Key
if f := StateTransitionTable[tupple]; f == nil {
fmt.Println("無效命令,請重試")
} else {
f(&p.s)
}
}
type StateCmdTupple struct {
s State
c string
}
type TransitionFunc func(s *State)
var StateTransitionTable = map[StateCmdTupple]TransitionFunc {
{Locked, CmdCoin}: func(s *State){
fmt.Println("已解鎖肋演,請通行抑诸。")
*s = Unlocked
},
{Locked, CmdPush}: func(s *State){
fmt.Println("禁止通行烂琴,請先投幣。")
},
{Unlocked, CmdCoin}: func(s *State){
fmt.Println("多投的幣會捐給國家蜕乡。")
},
{Unlocked, CmdPush}: func(s *State){
fmt.Println("請盡快通行奸绷,通過后閘機(jī)鎖定。")
*s = Locked
},
}
func prompt(s State) {
m := map[State]string{
Locked: "鎖定",
Unlocked: "解鎖",
}
fmt.Printf("閘機(jī)當(dāng)前的狀態(tài)是: [%s], 請輸入命令(coin或push)\n", m[s])
}
func main() {
machine := &Turnstile{Locked}
prompt(machine.s)
r := bufio.NewReader(os.Stdin)
for {
cmd, err := r.ReadString('\n')
if err != nil {
log.Fatalln(err)
}
machine.ExecuteCmd(cmd)
}
}