Go fsm

package fsm

import (
    "log"
)

type EvtIf interface {
    GetEvtType() string
}

type Action interface {
    //doAction(evt EvtIf, srcState *State, dstState *State)
    doAction(evt EvtIf)
}

type Transition struct {
    dstState *State
    action   Action
}

type State struct {
    name          string
    isEnd         bool
    transitionTbl map[string]Transition
}

type fsm struct {
    InstId        uint64
    version       uint32
    startPoint    *State
    current       *State
    transitionLog []Transition
    stateTbl      map[string]*State
}

//func StartStateMachine(transtionLog []Transition) *fsm {
//}
//func ReplyStateMachine(transtionLog []Transition) *fsm {
//}
//func Save() *fsm {
//}
//func Load() *fms {
//}

func NewState(name string, end bool) *State {
    return &State{name, end, map[string]Transition{}}
}

func (this *State) GetName() string {
    return this.name
}

func (this *State) InterestInEvt(evt EvtIf) bool {
    if evt == nil {
        return false
    }
    _, exists := this.transitionTbl[evt.GetEvtType()]
    return exists
}

func (this *State) AddTransition(evt EvtIf, dst *State, action Action) {
    if evt == nil || dst == nil || action == nil {
        log.Fatal("AddTransition error, parameter invalid!")
    }
    _, exists := this.transitionTbl[evt.GetEvtType()]
    if exists {
        log.Fatal("AddTransition error,EvtIf exist")
    }
    this.transitionTbl[evt.GetEvtType()] = NewTransition(dst, action)
}

func (this *State) GetTransition(evt EvtIf) *Transition {
    if evt == nil {
        return nil
    }

    tran, exists := this.transitionTbl[evt.GetEvtType()]
    if exists == false {
        log.Fatal("GetTransition error,EvtIf doesn't exist")
    }
    return &tran
}

func NewTransition(dstState *State, action Action) Transition {
    return Transition{dstState, action}
}

func (this *fsm) RegisterState(state *State) {
    if state == nil {
        log.Fatal("RegisterState error, parameter invalid!")
    }
    _, exists := this.stateTbl[state.GetName()]
    if exists {
        return
        log.Fatal("RegisterState error,State exist")
    }
    this.stateTbl[state.GetName()] = state
}

func (this *fsm) AddTransition(srcState *State, evt EvtIf, dstState *State, action Action) {
    if srcState == nil || dstState == nil || evt == nil || action == nil {
        log.Fatal("AddTransition error, parameter invalid!")
    }
    this.RegisterState(srcState)
    this.RegisterState(dstState)
    srcState.AddTransition(evt, dstState, action)
}

func (this *fsm) AddInternalTransition(srcState *State, evt EvtIf, action Action) {
    this.AddTransition(srcState, evt, srcState, action)
}

func (this *fsm) HandleEvt(evt EvtIf) {
    if evt == nil {
        return
    }

    srcState := this.current
    if srcState.InterestInEvt(evt) {
        transition := srcState.GetTransition(evt)
        log.Printf("Handle Event, srcState:%s, dstState:%s, evt:%s", srcState.GetName(), transition.dstState.GetName(), evt.GetEvtType())
        //transition.action.doAction(evt, srcState, transition.dstState)
        transition.action.doAction(evt)
        this.current = transition.dstState
    } else {
        log.Printf("parameter invalid, srcState:%s, evt:%s", srcState.GetName(), evt.GetEvtType())
    }
}

func NewFsm(initialState *State) *fsm {
    if initialState == nil {
        log.Fatal("NewFsm error, parameter invalid!")
    }
    return &fsm{initialState, map[string]*State{}}
}
原文地址:https://www.cnblogs.com/diegodu/p/5113737.html