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")
}

  

猜你喜欢

转载自www.cnblogs.com/mengxingxinqing/p/10939857.html