好处:逻辑收敛
1.状态转换更加清晰
2.新增转化逻辑,其他地方的代码不用修改
比如对于这样一个状态机:
|----|------------------------|
| 状态 | [草稿,审阅中,已拒绝,已通过,已归档] |
| 事件 | [提交,撤回,拒绝......] |

Go
If else写法:
func docIfElse(events []string) {
state := "草稿"
for _, e := range events {
fmt.Printf(" [%s] + <%s> → ", state, e)
if state == "草稿" && e == "提交" {
state = "审阅中"
} else if state == "审阅中" && e == "通过" {
state = "已通过"
} else if state == "审阅中" && e == "拒绝" {
state = "已拒绝"
} else if state == "审阅中" && e == "撤回" {
state = "草稿"
} else if state == "已拒绝" && e == "提交" {
state = "审阅中"
}
// ★ 新增状态?要在这里继续堆 else if...
fmt.Printf("%s\n", state)
}
}
状态机写法:
Go
状态机写法:
// ----- 基础类型 -----
type Transition struct {
Event string // 触发事件
Next string // 目标状态
}
type State struct {
Name string
IsEnd bool // 终态标记
Transitions []*Transition // 该状态的所有合法出口
}
type StateFlow []State
// ----- 引擎(永远不用改)-----
type FSM struct {
current string
flow map[string]*State
}
func NewFSM(flow StateFlow, initial string) *FSM {
m := make(map[string]*State, len(flow))
for i := range flow {
s := &flow[i]
m[s.Name] = s
}
return &FSM{current: initial, flow: m}
}
func (f *FSM) Handle(event string) {
st, ok := f.flow[f.current]
if !ok {
fmt.Printf(" ❓ 未知状态: %s\n", f.current)
return
}
if st.IsEnd {
fmt.Printf(" [%s] 是终态,不接受任何事件\n", f.current)
return
}
for _, t := range st.Transitions {
if t.Event == event {
fmt.Printf(" [%s] + <%s> → %s\n", f.current, event, t.Next)
f.current = t.Next
return
}
}
fmt.Printf(" [%s] + <%s> → 无效事件,保持原状态\n", f.current, event)
}
// ============================================================
// 定义文档审批流
// ============================================================
// 第一步:定义可复用的转换(定义一次,到处引用)
var (
submitTransition = &Transition{Event: "提交", Next: "审阅中"}
approveTransition = &Transition{Event: "通过", Next: "已通过"}
rejectTransition = &Transition{Event: "拒绝", Next: "已拒绝"}
withdrawTransition = &Transition{Event: "撤回", Next: "草稿"}
archiveTransition = &Transition{Event: "归档", Next: "已归档"}
)
// 第二步:以"状态"为中心,声明每个状态的合法出口
var docFlow = StateFlow{
{
Name: "草稿",
Transitions: []*Transition{
submitTransition, // → 审阅中
},
},
{
Name: "审阅中", // 表示审阅这个状态,可能会流转到已通过,已拒绝,草稿三个状态
Transitions: []*Transition{
approveTransition, // → 已通过
rejectTransition, // → 已拒绝
withdrawTransition, // → 草稿
},
},
{
Name: "已拒绝",
Transitions: []*Transition{
submitTransition, // → 审阅中(复用同一个对象!)
},
},
{
Name: "已通过",
Transitions: []*Transition{
archiveTransition, // → 已归档
},
},
{
Name: "已归档",
IsEnd: true, // 终态
},
}
func main() {
fsm := NewFSM(docFlow, "草稿")
events := []string{"提交", "拒绝", "提交", "通过", "归档", "提交"}
for i, e := range events {
fmt.Printf("[步骤 %d] ", i+1)
fsm.Handle(e)
}
}