zoukankan      html  css  js  c++  java
  • 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")
    }
    

      

  • 相关阅读:
    高并发的一些处理意见
    TP5单元测试
    你真的会玩SQL吗?和平大使 内连接、外连接
    微信公众号第三方平台开发概况
    MVC的基类
    Android TextView中显示图片
    Android之assets资源
    通用分页存储过程
    到处都是坑的微信支付V3之 微信支付回调页面
    微信公众平台无高级接口账号获取用户基本信息
  • 原文地址:https://www.cnblogs.com/mengxingxinqing/p/10939857.html
Copyright © 2011-2022 走看看