UML状态图完全指南:从入门到画好一张专业的状态机图

UML 状态图完全指南,从零基础入门掌握 UML 状态机图,讲解状态、转移、监护条件、嵌套状态语法,附带实战案例,教你画出专业规范的 UML 状态图,分清状态图与活动图差异,适合软件设计、系统建模学习。

UML状态图完全指南

状态图(State Machine Diagram)是UML中描述对象生命周期的重要工具。一张清晰的状态图,能让团队在10秒内理解一个对象从创建到销毁的完整流转逻辑。本文从核心概念到进阶建模,系统讲解状态图的绘制方法与避坑要点。


一、状态图是什么?解决什么问题?

状态图用于描述一个对象在其生命周期内,响应各种事件时经历的状态序列。它回答的核心问题是:"这个对象在什么条件下,从什么状态变成什么状态?"

适用场景包括:

  • 订单生命周期管理(创建→支付→发货→收货→完成)
  • 用户账号状态流转(注册→激活→正常→冻结→注销)
  • 审批流程状态机(提交→审核中→通过/驳回→归档)
  • 嵌入式设备控制(待机→运行→暂停→故障→恢复)
  • 协议通信状态机(连接建立→数据传输→连接关闭)

状态图 vs 流程图的关键区别流程图描述的是"做事的过程",状态图描述的是"对象的变化"。如果关注的是一条数据从生到死的全部状态,用状态图;如果关注的是一系列步骤的执行顺序,用流程图



二、状态图的四大核心要素

要素 符号 说明 示例
状态(State) 圆角矩形 对象在某一时刻的稳定状况 "待支付"、"已发货"
初始状态 实心圆 对象创建时的起点,每张图只有一个
终止状态 圆中套环 对象生命周期的终点,可以多个
转移(Transition) 带箭头的直线 从一个状态到另一个状态的跳转

转移的完整语法

一条完整的转移包含三个部分,语法格式为:

事件名 [监护条件] / 动作
  • 事件名:触发转移的外部动作,用动词短语。如"点击支付"、"超时10分钟"
  • 监护条件:方括号包裹的布尔表达式,条件为真时才执行转移。如"[金额>0]"
  • 动作:斜杠后跟的具体操作,可选。如"/扣除库存"

完整示例:

点击支付 [订单未超时 && 金额>0] / 调用支付接口

这三个部分都是可选的,但省略得越多,模型的信息量就越少。专业状态图中,每条转移至少应该标注事件名。


三、状态内部行为:entry、do、exit

状态不仅仅是"等着",一个状态内部可以包含三种行为:

行为类型 触发时机 语法 示例
entry 进入状态时执行 entry/ 动作 entry/ 启动定时器
do 处于状态期间持续执行 do/ 动作 do/ 监听支付回调
exit 离开状态时执行 exit/ 动作 exit/ 记录日志

在圆角矩形内部,状态名写在顶部,行为写在分隔线下方:

┌─────────────────────┐
│     支付中           │
├─────────────────────┤
│ entry/ 启动10分钟定时器│
│ do/ 等待支付网关回调   │
│ exit/ 清除定时器       │
└─────────────────────┘

这三种行为让状态图不仅描述"状态怎么变",还能描述"每个状态里干什么"。


四、组合状态:管理复杂性的关键

当状态数量超过8-10个时,单层状态图会变得难以阅读。此时应使用组合状态(Composite State),将相关子状态归组到一个父状态内部。

组合状态结构

┌──────────────────────────────────┐
│          订单处理中                 │
│  ┌──────┐    ┌──────┐    ┌──────┐ │
│  │待发货 │ →  │已发货 │ →  │待收货 │ │
│  └──────┘    └──────┘    └──────┘ │
│  entry/ 通知仓库                    │
│  exit/  发送完成短信                 │
└──────────────────────────────────┘

组合状态的核心价值:

  1. 层次化抽象:高层看"订单处理中",低层看内部三个子状态
  2. 共享行为:父状态的entry/exit对子状态生效,减少重复标注
  3. 可扩展性:新增子状态不影响其他部分的阅读

历史状态



组合状态支持历史状态(History State),用圆圈中字母H表示。当对象离开组合状态后再次返回时,可以从上次离开的子状态继续,而不是从头开始。

典型场景:播放器暂停后恢复,从上次播放的位置继续。


五、五步绘制法:从零画出专业状态图

第一步:确定建模对象

状态图只描述一个对象的生命周期。先明确你要画的是"订单"还是"用户"还是"审批单",不要把多个对象混在一张图里。

判断标准:如果发现状态名属于不同对象(如"订单已创建"和"用户已登录"),说明需要拆成多张图。

第二步:列出所有状态

用穷举法列出对象从创建到销毁的所有可能状态。

技巧:用名词或形容词命名状态,不用动词。"待支付"是状态,"支付"是动作。一个常见错误是把动作当状态——"验证密码"是动作,"验证中"或"已验证"才是状态。

第三步:标注初始状态和终止状态

每张状态图有且只有一个初始状态(实心圆),可以有零到多个终止状态(圆中套环)。

不是所有对象都有终止状态。例如"用户账号"可能永远不会真正"终止",只是被"冻结"。

第四步:连接转移并标注事件

在状态之间画箭头,标注触发转移的事件、监护条件和动作。

三个关键检查点:

  • 每个非终止状态至少有一个出转移(否则对象会"卡死")
  • 同一状态出发的多条转移,事件名不能相同(除非监护条件互斥)
  • 终止状态没有任何出转移

第五步:补充异常路径

这是最容易被遗漏的一步。只画主流程的状态图是不完整的,必须补充:

  • 超时路径:如"支付中"超时10分钟→"支付失败"
  • 取消路径:如"待支付"用户取消→"已取消"
  • 回退路径:如"支付失败"→"待支付"(用户重新支付)
  • 异常路径:如"支付中"→"异常处理中"(系统错误)

补充原则:对每个非终止状态都问一句——"如果出错了会怎样?如果超时了会怎样?如果用户放弃了会怎样?"


六、五个常见错误及修正

错误1:把流程图画成状态图

表现:把"用户点击按钮→系统验证→返回结果"画成状态图。

问题:这是一系列动作的执行顺序,不是对象状态的变迁。应该用流程图或活动图。

判断标准:如果你的"状态"其实是"动作步骤"(第一步、第二步……),用流程图;如果你的节点描述的是对象"处于什么状况",用状态图。

错误2:状态爆炸

表现:一张图上有20多个状态,箭头交叉如蜘蛛网。

修正

  • 用组合状态归组相关子状态
  • 拆分成多张图,每张描述一个子生命周期
  • 检查是否有"伪状态"(属性变化不应该是独立状态)

错误3:转移条件模糊

表现:箭头上只写"用户重试",没有说明在什么条件下可以重试。

修正:补充监护条件,如"用户重试 [订单未超时 && 24小时内重试次数<3]"。模糊的条件会导致开发落地时理解偏差。

错误4:遗漏异常状态

表现:只画了"待支付→支付中→支付成功",没有"支付失败"、"退款中"等异常状态。

修正:对每个状态执行异常检查——超时怎么办?出错怎么办?用户取消怎么办?

错误5:事件与状态命名混淆

表现:状态名用动词(如"支付"),事件名用名词(如"订单")。

修正规范

  • 状态名用形容词或进行时:"待支付"、"运行中"、"已锁定"
  • 事件名用动宾短语或过去时:"点击支付"、"超时"、"收到回调"


七、进阶建模技巧

1. 正交区域

当一个对象同时具有多个独立的状态维度时,使用正交区域将组合状态分为并行区域。

例如手机同时有电源状态(开/关)和网络状态(在线/离线),这两个维度独立变化,应放在同一组合状态的正交区域内并行描述。

2. 子状态机引用

当一部分状态逻辑在多个地方复用时,将其封装为独立的子状态机,在主图中用"引用"方式调用,类似于代码中的函数调用。

3. 延迟事件

有些事件在当前状态下无法处理,但希望在未来某个状态下处理。可以标注为延迟事件(defer),表示该事件被暂存,直到进入能处理它的状态时再触发。


八、工具选择建议

工具类型 推荐工具 特点
在线画图 singcheng.com 支持状态图绘制,在线协作,无需安装
代码生成 PlantUML 用文本描述生成图表,适合纳入版本管理
专业建模 Visual Paradigm 功能全面,支持完整UML规范
轻量工具 Draw.io 免费开源,上手快

选择原则:如果团队需要协作评审,优先选在线协作工具;如果需要纳入技术文档版本管理,PlantUML更合适。在 singcheng.com 上可以直接绘制状态图并实时协作,适合团队评审场景。


九、状态图自检清单

画完状态图后,逐项检查:

  • 只描述了一个对象的生命周期
  • 状态名使用名词/形容词,事件名使用动词短语
  • 有且只有一个初始状态
  • 每个非终止状态至少有一个出转移
  • 每条转移至少标注了事件名
  • 同一状态的多个出转移,事件互斥或有不同监护条件
  • 补充了超时、取消、异常等非主流程路径
  • 状态数量超过10个时使用了组合状态
  • 终止状态没有任何出转移
  • 所有状态从初始状态可达

总结

状态图的核心价值不在于画图本身,而在于通过绘制过程,迫使对系统行为进行深入、结构化的思考,最终产出一份无歧义的设计契约。

掌握状态图的关键在于三点:选对建模对象(只画一个对象)、区分状态与动作(状态是状况,动作是操作)、穷举异常路径(不只画主流程)。

更多画图教程与实战案例,尽在 singcheng.com。


发布平台:星程图示· Singcheng