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