状态机常用于状态流转,尤其是对于复杂业务,通常涉及到复杂的状态流转逻辑
本文实现了一种简单的状态机,并通过友好的方式提供使用接口
状态机可以用状态图标识,包含两个元素:
节点:节点即状态的标识,有多少种状态就有多少个节点
连线:根据连线的不同可分为有向连线和无向连线,代表着状态流转的触发条件
如下图就是一个简单的状态图
import (
"fmt"
)
const (
StateStart = "start"
StateEnd = "end"
)
type StateMachine struct {
is any // 初始状态
fs any // 终止状态
g map[any]map[any]map[any]int // 有向图 s1 -> s2 -> trigger
as states // 所有状态
}
func (s *StateMachine) Permit(from, to any, triggers ...any) *StateMachine {
if _, ok := s.g[from]; !ok {
s.g[from] = make(map[any]map[any]int)
}
if _, ok := s.g[from][to]; !ok {
s.g[from][to] = make(map[any]int)
}
for _, trigger := range triggers {
s.g[from][to][trigger] = 1
}
if !s.as.contains(from) {
s.as = append(s.as, from)
}
if !s.as.contains(to) {
s.as = append(s.as, to)
}
return s
}
func (s *StateMachine) PathThrough(from, to any, triggers ...any) bool {
if _, ok := s.g[from]; !ok {
return false
}
if _, ok := s.g[from][to]; !ok {
return false
}
for _, trigger := range triggers {
if _, ok := s.g[from][to][trigger]; !ok {
return false
}
}
return true
}
func (s *StateMachine) Next(from any, trigger any) (to any, ok bool) {
if _, ok = s.g[from]; !ok {
return nil, false
}
for to, m := range s.g[from] {
if _, ok = m[trigger]; ok {
return to, true
}
}
return nil, false
}
func New() *StateMachine {
return &StateMachine{
is: StateStart,
fs: StateEnd,
g: make(map[any]map[any]map[any]int),
}
}