golang 状态机
package main import ( "errors" "fmt" "reflect" ) type State interface { Name() string EnableSameTransit() bool OnBegin() OnEnd() CanTransitTo(name string) bool } func StateName(s State) string { if s == nil{ return "none" } return reflect.TypeOf(s).Elem().Name() } type StateInfo struct { name string } func (s *StateInfo) Name() string { return s.name } func (s *StateInfo) setName(name string){ s.name = name } //是否能够同状态转移 func (s *StateInfo) EnableSameTransit()bool{ return false } func (s *StateInfo) OnBegin(){ } func (s *StateInfo) OnEnd(){ } //是否能够转移到状态 func (s *StateInfo) CanTransitTo(name string) bool{ return true } type StateManager struct { stateByName map[string]State Onchange func(from,to State) curr State } func (sm *StateManager) Add(s State){ name := StateName(s) s.(interface{ setName(name string) }).setName(name) if sm.Get(name)!=nil{ panic("重复添加:"+name) } sm.stateByName[name] = s } func (sm *StateManager) Get(name string) State { if v,ok:=sm.stateByName[name];ok{ return v } return nil } func NewStateManager()*StateManager{ return &StateManager{ stateByName:make(map[string]State), } } var ErrForbidSameTransit = errors.New("ErrForbidSameTransit") var ErrCannotTransitToState = errors.New("ErrCannotTransitToState") var ErrStateNotFound = errors.New("ErrStateNotFound") func (sm *StateManager)CurrState()State { return sm.curr } func (sm *StateManager) CanCurrTransitTo(name string)bool { if sm.curr == nil{ return true } if sm.curr.Name() == name && !sm.curr.EnableSameTransit(){ return true } return sm.curr.CanTransitTo(name) } func (sm *StateManager) Transit(name string)error{ next := sm.Get(name) if next==nil{ return ErrStateNotFound } pre := sm.curr if sm.curr!=nil{ if sm.curr.Name() == name && !sm.curr.EnableSameTransit(){ return ErrForbidSameTransit } if !sm.CanCurrTransitTo(name){ return ErrCannotTransitToState } sm.curr.OnEnd() } sm.curr = next sm.curr.OnBegin() if sm.Onchange!=nil{ sm.Onchange(pre,sm.curr) } return nil } type IdleState struct { StateInfo } func (i *IdleState)OnBegin() { fmt.Println("idle on begin") } func (i *IdleState)OnEnd() { fmt.Println("idle on end") } type MoveState struct { StateInfo } func (i *MoveState)OnBegin() { fmt.Println("move on begin") } func (i *MoveState)OnEnd() { fmt.Println("move on end") } func (i *MoveState)EnableSameTransit() bool { return true } type JumpState struct { StateInfo } func (i *JumpState)OnBegin() { fmt.Println("jump on begin") } func (i *JumpState)OnEnd() { fmt.Println("jump on end") } func (i *JumpState) CanTransitTo(name string) bool { return name != "MoveState" } func main() { sm := NewStateManager() sm.Onchange = func(from, to State) { fmt.Println("from",from,"to",to) } sm.Add(new(IdleState)) sm.Add(new(JumpState)) sm.Add(new(MoveState)) sm.Transit("JumpState") sm.Transit("IdleState") sm.Transit("MoveState") }