- package main
-
- import (
- "fmt"
- "gonum.org/v1/gonum/graph"
- "gonum.org/v1/gonum/graph/multi"
- )
-
- /*
- 基于gonum定义节点和边
- */
-
- type State struct {
- Id int64
- Value interface{}
- }
-
- type Link struct {
- Id int64
- T, F graph.Node
- Event Event
- }
-
- func (n State) ID() int64 {
- return n.Id
- }
-
- func (n State) String() string {
- return n.Value.(string)
- }
-
- func (l Link) From() graph.Node {
- return l.F
- }
-
- func (l Link) To() graph.Node {
- return l.T
- }
-
- func (l Link) ID() int64 {
- return l.Id
- }
-
- func (l Link) ReversedLine() graph.Line {
- return Link{F: l.T, T: l.F}
- }
-
- /*
- 定义FSM
- */
-
- type Event string
-
- var NodeIDCnt = 0
- var LineIdCnt = 1
-
- type StateMachine struct {
- PresentState State
- g *multi.DirectedGraph
- }
-
- func New() *StateMachine {
- s := &StateMachine{}
- s.g = multi.NewDirectedGraph()
- return s
- }
-
- func (s *StateMachine) InitState(initValue interface{}) State {
- s.PresentState = s.NewState(initValue)
- return s.PresentState
- }
-
- func (s *StateMachine) NewState(stateValue interface{}) State {
- state := State{Id: int64(NodeIDCnt), Value: stateValue}
- s.g.AddNode(state)
- NodeIDCnt++
- return state
- }
-
- func (s *StateMachine) LinkStates(s1, s2 State, event Event) {
- s.g.SetLine(Link{F: s1, T: s2, Id: int64(LineIdCnt), Event: event})
- LineIdCnt++
- }
-
- // FireEvent 触发事件
- func (s *StateMachine) FireEvent(e Event) error {
- presentNode := s.PresentState
-
- it := s.g.From(presentNode.Id)
-
- for it.Next() {
- to := s.g.Node(it.Node().ID()).(State)
- line := graph.LinesOf(s.g.Lines(presentNode.Id, to.Id))[0].(Link)
- if line.Event == e {
- s.PresentState = to
- return nil
- }
- return fmt.Errorf("没有对应的事件:%s", e)
- }
- return nil
- }
-
- // Compute 批量触发处理
- func (s *StateMachine) Compute(events []string, printState bool) State {
- for _, e := range events {
- previousState := s.PresentState
- err := s.FireEvent(Event(e))
- if err != nil {
- panic(err)
- }
- if printState {
- fmt.Printf("触发事件[%s]后,状态由[%s]变为了[%s]\n", e, previousState, s.PresentState.String())
- }
- }
- return s.PresentState
- }
-
- func main() {
- //构造有向图
- stateMachine := New()
- lockedState := stateMachine.InitState("locked")
- unlockedSate := stateMachine.NewState("unlocked")
-
- coinEvent := Event("coin")
- pushEvent := Event("push")
-
- stateMachine.LinkStates(lockedState, unlockedSate, coinEvent)
- stateMachine.LinkStates(unlockedSate, lockedState, pushEvent)
-
- stateMachine.LinkStates(lockedState, lockedState, pushEvent)
- stateMachine.LinkStates(unlockedSate, unlockedSate, coinEvent)
-
- //触发事件
- fmt.Printf("初始状态: %s\n", stateMachine.PresentState.String())
-
- events := []string{"coin", "push"}
- stateMachine.Compute(events, true)
-
- fmt.Printf("最终状态: %s\n", stateMachine.PresentState.String())
-
- }
初始状态: locked
触发事件[coin]后,状态由[locked]变为了[unlocked]
触发事件[push]后,状态由[unlocked]变为了[locked]
最终状态: locked