Skip to content

gaoziyin/StateMachinePatterns

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎯 状态机模式:驾驭复杂性的艺术

State machine patterns by C#/.Net

"复杂性不是问题,失控的复杂性才是。"

📚 项目索引

# 项目 领域 核心概念
1 基础状态机 入门 状态、转换、事件
2 异步状态机 企业 async/await、并发控制
3 嵌套状态机 企业 层次状态、子状态机
4 并行状态机 企业 正交区域、同步状态
5 历史状态机 企业 状态记忆、恢复机制
6 事件驱动状态机 企业 发布订阅、解耦
7 表驱动状态机 企业 配置化、运行时加载
8 持久化状态机 企业 数据库存储、断点续传
9 Boss战状态机 游戏 多阶段、AI行为
10 格斗连招系统 游戏 输入缓冲、帧数据
11 潜行AI系统 游戏 感知系统、警戒等级
12 回合制战斗 游戏 行动队列、状态效果
13 赛车载具系统 游戏 物理状态、损坏系统

🧠 状态机的本质洞察

什么是状态机?

状态机是一种思维模型,它告诉我们:

任何复杂系统,在任意时刻,都处于某个明确的状态;
系统只能通过定义好的转换,从一个状态迁移到另一个状态。

这个简单的约束,带来了强大的控制力。

为什么状态机如此强大?

                    ┌─────────────────────────────────────────┐
                    │           复杂性的来源                   │
                    └─────────────────────────────────────────┘
                                      │
              ┌───────────────────────┼───────────────────────┐
              │                       │                       │
              ▼                       ▼                       ▼
        ┌──────────┐           ┌──────────┐           ┌──────────┐
        │ 状态爆炸  │           │ 转换混乱  │           │ 边界模糊  │
        │          │           │          │           │          │
        │ if-else  │           │ 意外转换  │           │ 非法状态  │
        │ 嵌套地狱  │           │ 难以追踪  │           │ 竞态条件  │
        └──────────┘           └──────────┘           └──────────┘
              │                       │                       │
              └───────────────────────┼───────────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────────────┐
                    │           状态机的解决方案               │
                    │                                         │
                    │  ✅ 状态明确定义                        │
                    │  ✅ 转换显式声明                        │
                    │  ✅ 非法路径不存在                       │
                    │  ✅ 行为与状态绑定                       │
                    └─────────────────────────────────────────┘

🏭 生产领域的启发

1. 订单生命周期管理

传统思维: "订单有很多字段,我们检查字段来判断状态"
状态机思维: "订单本身就是状态的载体,状态决定可用操作"

┌────────────────────────────────────────────────────────────────┐
│                                                                │
│   Created → Paid → Processing → Shipped → Delivered → Closed  │
│      │                              │                          │
│      └──────── Cancelled ◄──────────┘                          │
│                                                                │
└────────────────────────────────────────────────────────────────┘

启发: 状态不是派生属性,而是系统的第一公民

2. 工作流引擎

审批流、报销流、发布流...

传统做法: 硬编码每个节点的判断逻辑
状态机做法: 流程即配置,状态即节点,转换即连线

启发: 将"流程"从代码中解放出来,变成可配置的数据

3. 微服务编排

Saga模式本质上就是分布式状态机:

LocalTransaction₁ → LocalTransaction₂ → LocalTransaction₃
        │                    │                  │
        ▼                    ▼                  ▼
   Compensate₁ ◄───── Compensate₂ ◄───── Compensate₃

启发: 复杂的分布式事务,可以用状态机建模和恢复

4. 设备控制

IoT设备状态: Offline → Connecting → Online → Working → Error

每个状态有明确的:
  - 允许的操作
  - 监控指标
  - 告警规则
  - 恢复策略

启发: 状态机让设备行为可预测、可监控、可恢复

🌍 生活中的状态机

1. 交通信号灯

最经典的状态机例子:

    ┌──────┐    60秒    ┌──────┐    5秒     ┌──────┐
    │ 🟢  │ ────────→ │ 🟡  │ ────────→ │ 🔴  │
    │ 绿灯 │           │ 黄灯 │           │ 红灯 │
    └──────┘           └──────┘           └──────┘
         ▲                                    │
         │              60秒                  │
         └────────────────────────────────────┘

启发: 明确的状态 + 明确的规则 = 安全的系统

2. 人生阶段

童年 → 青年 → 壮年 → 老年

每个阶段:
  - 有其独特的责任和权利
  - 有向下一阶段的转换条件
  - 无法跳跃或逆转(物理意义上)

启发: 状态机帮助我们接受"阶段性"思维
       当前状态决定当前选择,而非无限可能

3. 情绪管理

平静 ──(刺激)──→ 愤怒 ──(冷静)──→ 反思 ──(释然)──→ 平静
  │                │
  │                └──(失控)──→ 后悔
  │                                │
  └───────────────(时间)───────────┘

启发: 认识到情绪是"状态"而非"本质"
       我们可以设计"转换规则"来管理情绪

4. 习惯养成

                    ┌─────────────────────┐
                    │    舒适区 (默认)     │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │    尝试 (行动)       │◄──┐
                    └──────────┬──────────┘   │
                               │              │
              ┌────────────────┼────────────┐ │
              │                │            │ │
    ┌─────────▼───────┐ ┌──────▼─────┐     │ │
    │  放弃 (回退)     │ │  坚持      │─────┘ │
    │                 │ └──────┬─────┘       │
    └────────┬────────┘        │             │
             │                 │             │
             │        ┌────────▼────────┐    │
             │        │   习惯 (新常态)  │    │
             │        └─────────────────┘    │
             │                               │
             └───────────────────────────────┘

启发: 改变是状态转换,需要足够的"能量"突破阈值
       一旦进入新状态,维持成本降低

🎮 游戏开发的深度应用

1. AI行为树 vs 状态机

状态机: 适合有限、明确的行为模式
  例: 守卫的 巡逻→怀疑→警觉→战斗

行为树: 适合复杂、层次化的决策
  例: 战略AI的多目标权衡

混合方案: 行为树做决策,状态机做执行
  "决定做什么" vs "怎么做"

2. 动画状态机

Idle ←→ Walk ←→ Run
  ↓       ↓       ↓
Jump   Jump    Jump
  ↓       ↓       ↓
Fall   Fall    Fall
  ↓       ↓       ↓
Land   Land    Land

动画混合 = 状态间的插值过渡
动画事件 = 状态中的时间触发器

启发: 状态机天然适合处理"互斥"的行为
       人不能同时站立和奔跑

3. 游戏状态管理

Loading → MainMenu → Playing → Paused → GameOver
                        ↑         │
                        └─────────┘

每个状态管理自己的:
  - UI层级
  - 输入响应
  - 资源加载
  - 音频控制

启发: 状态机是游戏架构的骨架

4. 网络同步

客户端状态机 + 服务端权威 + 状态预测 + 回滚

Predicted → Confirmed
     ↓           ↓
 Rollback ← Mismatch

启发: 分布式系统的一致性,本质是状态同步

💡 状态机的设计哲学

原则一:状态应该是互斥的

❌ 错误: isMoving && isAttacking && isJumping (同时为真?)
✅ 正确: State = { Idle, Moving, Attacking, JumpAttacking }

每个状态组合应该是一个独立状态

原则二:转换应该是原子的

❌ 错误: 部分完成的状态转换
✅ 正确: 要么完全转换,要么保持原状态

状态转换是事务

原则三:状态应该封装行为

❌ 错误: 外部检查状态然后执行对应逻辑
✅ 正确: 状态自己知道该做什么

switch(state) {           vs      state.Update()
  case A: doA(); break;           state.HandleInput()
  case B: doB(); break;           state.Render()
}

原则四:转换条件应该明确

❌ 错误: "当差不多的时候转换"
✅ 正确: "当HP < 30% && 距离 > 10m时转换到Flee状态"

模糊的条件导致不可预测的行为

🔮 更高层次的抽象

状态机与生命周期

一切有"生命"的事物,都可以用状态机建模:

进程:   Created → Ready → Running → Waiting → Terminated
连接:   Closed → Opening → Open → Closing → Closed
事务:   Pending → Processing → Committed/Rolledback
请求:   Sent → Received → Processing → Responded

状态机与时间

状态机本质上是对"时间流逝"的建模:

过去 ─────────────────────────────────────→ 未来
     │         │          │          │
     状态A  → 转换 →    状态B  →   转换 → ...
     
时间是单向的,状态转换也应该有方向性
(虽然可以"返回"某个状态,但那是新的转换,不是时间回溯)

状态机与确定性

相同的初始状态 + 相同的事件序列 = 相同的最终状态

这就是为什么状态机:
  ✅ 易于测试 (可重放)
  ✅ 易于调试 (可追踪)
  ✅ 易于理解 (可预测)

🎓 总结:状态机教会我们什么

1. 拥抱有限性

"我不能同时处于所有状态"

这不是限制,而是解放。
有限的状态意味着有限的复杂度。

2. 尊重过程

"从A到C,必须经过B"

不是所有目标都能直达。
状态机帮助我们设计必经之路。

3. 活在当下

"当前状态决定当前可能"

过去的状态已经退出,未来的状态尚未进入。
专注于当前状态的职责。

4. 接受转换

"变化是必然的,但变化是有规则的"

我们无法阻止变化,但可以设计变化的规则。
好的状态机让变化可控、可预测、可追溯。

🚀 从模式到思维

状态机不仅是一个编程模式,更是一种思维方式:

当你面对复杂系统时,问自己:

1. 这个系统有哪些互斥的状态?
2. 每个状态下,系统应该表现出什么行为?
3. 什么条件触发状态转换?
4. 哪些转换是允许的,哪些是禁止的?
5. 如何处理意外情况和错误恢复?

回答完这些问题,你就有了状态机的骨架。

📖 结语

"简单的规则产生复杂的行为, 复杂的规则产生混乱的行为。"

— 复杂系统理论

状态机的魔力在于:用简单、明确的规则,构建出复杂但可控的系统。

无论是一个订单的生命周期,还是一个Boss的战斗AI; 无论是一段感情的发展,还是一个产品的迭代; 状态机的思维都能帮助我们:

看清当下,规划转换,走向期望的状态。


本项目包含13个状态机示例,涵盖企业应用和游戏开发两大领域。 每个示例都是独立可运行的 .NET 10 / C# 14 项目。

# 运行任意示例
cd "1. 基础状态机"
dotnet run

Happy State Machining! 🎯

About

State machine patterns by C#/.Net

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages