软件分析与设计笔记 28:draw.io 作图手册:五张图的符号位置、落笔顺序与自检

不模拟软件界面,只讲清三件事:每个 UML 符号在 draw.io 里搜什么词、一张图该按什么顺序落笔、画完拿什么标准自查。覆盖用例图、活动图、顺序图、类图、界面草图五种图纸,末尾附「最容易画反的十二笔」总检表。

学习#应试#UML#绘图#学习笔记

本文是 《软件分析与设计笔记》 系列的第 28 篇,共 28 篇

这是我把课程里所有画图要求整理成的一份作图手册。符号与方向规则来自课程讲义、workshop 批改批注与 UML 规范;draw.io 的操作要点是我自己在用的路径。工具版本更新后菜单文字可能变,所以优先给搜索词和属性名,而不是菜单路径。理解有偏差的地方欢迎指出。

0 画对了,但被扣分了

一份作业交上去,回来的批注往往只有几个词:Wrong notation、Wrong direction、Wrong access。

问题不在「不会画」—— 大多数人看图是看得懂的。问题在于画的时候没有区分「读」和「写」、「包含」和「扩展」、「聚合」和「组合」。这些差别在口语里都可以含糊过去,但图上差一笔就是差一笔的分。

这篇不模拟软件界面(那种图一改版就废),只解决三个具体问题:

  1. 这个符号在哪里? —— 每个 UML 元素给一个搜索词,搜到就能拖;
  2. 先画什么后画什么? —— 每种图的落笔顺序,照做不会返工;
  3. 画完怎么自查? —— 一张对照表,逐条打勾。

三件事对上了,画图就不再是「凭感觉」。

1 开始之前:两个位置和一套属性

1.1 形状库在哪里

draw.io 的界面只有三个位置需要记。不需要记菜单文字,只需要记住形状库在左边、格式面板在右边:

text
┌────────────────────────────────────────────┐
│  工具栏(撤销、导出、缩放)                  │
├────────────┬───────────────────────────────┤
│            │                               │
│  形状库     │           画布                 │
│  ◄ 在这里   │                               │
│            │                               │
│  [搜索框]   │                               │
├────────────┴───────────────────────────────┤
│  格式面板(选中对象后才出现)◄ 在这里         │
└────────────────────────────────────────────┘

第一步永远是打开 UML 形状库:左下角 More Shapes(有的版本叫 + More Shapes)→ 勾选 UML → 应用。没勾之前,左侧搜不到 actor、boundary 这些词。

1.2 三个动作覆盖 90% 的操作

想做什么怎么做
加一个形状在搜索框打词 → 拖进画布
改文字双击形状(不是单击)→ 直接打字
连一条线鼠标移到形状边缘,出现小箭头 → 拖到目标形状

连线的关键是「出现小箭头」。如果拖出来的是虚线框,说明点到形状内部了,不是边缘。

1.3 端点样式:菱形和三角都靠它

这是全篇最值钱的一条。聚合、组合、继承这三种符号不在形状库里,它们都是通过改连线的端点样式画出来的。

选中一条线后,右侧格式面板找到 Line 一栏(找不到就点面板底部的 + 展开):

想要的符号操作
空心三角(继承)端点选 block 或 open arrow,然后设 filled = 0
空心菱形(聚合)端点选 diamond,设 filled = 0
实心菱形(组合)端点选 diamond,设 filled = 1
开放箭头(依赖/转移)端点选 open arrow
实心箭头(消息)端点选 block

记不住菜单就记属性名。在格式面板底部点 Edit Style,直接打进这串:

text
endArrow=block;endFill=0;      ← 空心三角
endArrow=diamond;endFill=0;    ← 空心菱形
endArrow=diamond;endFill=1;    ← 实心菱形

属性名比菜单文字稳定得多,跨版本都认。

2 先决定画哪张图

六个题型对应五类图纸(坏味道那题最终也落成一张类图),选错图纸等于答错题:

题目问的是该画的图不该画的图
系统做什么、谁在用用例图类图(静态结构答不了「谁用」)
一个用例的流程怎么走活动图顺序图(顺序图看不到分支和泳道)
一次交互由哪些对象按什么顺序协作顺序图活动图(活动图没有对象职责)
有哪些类、它们什么关系类图活动图
界面长什么样界面草图 + 隐喻说明UML 任何图
这段代码哪里不对坏味道说明 + 重构后的类图顺序图(问题不在交互)

有一条容易忽略的规律:同一份需求,这五类图是逐层细化的关系,不是五种并列的画法。用例给出边界,活动图给出流程,实体来自流程,顺序图把流程摊到对象上,类图再从顺序图机械导出,最后界面把流程落到屏幕上。

从需求到图纸的推导链:用例图确定边界与角色,活动图展开流程与泳道,业务实体从流程中提取并挂回活动图,顺序图把流程摊到边界、控制、实体三类对象上,类图从顺序图机械导出,界面草图把流程映射到屏幕;箭头表示每一层的输入来自上一层

这条链在实操上有直接用处:如果一张图卡住了,往往是因为上一层的产物没想清楚。做不出顺序图,通常是 basic flow 没读透;抽不出实体,通常是活动图里的步骤写得太粗。

3 用例图:四个地方会扣分

3.1 符号与落笔顺序

元素搜索词关键要求
参与者(actor)actor火柴人,一律在系统边界外
用例(use case)use case椭圆,名字用动宾短语
系统边界(system boundary)boundary矩形框,所有用例在框内
关联(communication association)直接连线实线,多数情况不带箭头

落笔顺序(按这个顺序不会返工):

  1. 先画边界框,拉大一点(要装下 8–12 个椭圆);
  2. 再摆 actor,全部放在框外左右两侧;
  3. 然后放用例,一列排或两列排,同类用例靠近;
  4. 最后连线 —— 先连主体角色,再连例外角色。

如果把连线留到最后,改布局时线会跟着乱;反过来先连线再挪形状,容易连错对象。

一个省力技巧:画完第一个 actor 后按 Ctrl+D 复制,比重新搜快。复制出来的形状位置会偏一点,用方向键微调比拖更准。

3.2 箭头方向:什么时候才需要箭头

这是用例图上最容易被忽略的细节。讲义的原话是:

  • 箭头由 actor 指向用例 —— 参与者主动触发,也就是用户点了什么;
  • 箭头由用例指向 actor —— 用例先启动,去唤醒参与者,通常是定时器或传感器触发的通知、邮件、告警。

所以大多数线其实不需要箭头(画实线即可)。只有当这条交互是「系统主动推送」时,才要把箭头画向 actor。一句提醒:如果一张用例图上每一根线都带箭头,那这张图基本可以确定画错了。

在贯穿案例里,「每日 9 点给当日有单的工程师发排期提醒」这一条,箭头就该由用例指向 Engineer——是系统主动推的。

3.3 三种精炼关系的方向

这是全卷最集中的扣分点,一定要记成条件反射:

关系箭头方向线上的标注条件写法
include基用例 → 被包含用例«include»无条件(每次必执行)
extend扩展用例 → 基用例«extend»条件写在箭头旁,不加方括号
泛化(用例/actor)子 → 父,空心三角无无

三个判断要点:

  1. include 和 extend 的箭头方向是相反的,这是唯一的记忆锚点。记法:include 是「我需要它」(箭头朝被需要的一方),extend 是「我附加到它」(箭头朝被附加的一方);
  2. 线是实线还是虚线都可以,讲义明确说两种都行 —— 所以不要在这上面纠结,方向才是分;
  3. extend 的条件不加方括号(那是活动图 guard 的写法)。

«include» 标签怎么加:画好连线后双击线的中间位置,打 «include»。尖括号可以直接打中文输入法的 « »,或者用 <<include>>(两个小于号),draw.io 都识别。 如果打出来显示成方块,说明字体缺字,换 <<include>> 写法即可。

3.4 参与者的合并与拆分

讲义给了两条方向相反的判断:

  • 用同一套用例、只是权限或待遇不同的 → 合并成一个 actor,差异写成业务规则(放在活动图里);
  • 访问的用例集不同 → 拆成两个 actor(或做泛化)。

案例里如果出现「普通客户」和「延保客户」这类区分,先别急着建两个 actor:问一句「他们做的事一样吗」。一样就合并。

3.5 一个用例连两个火柴人:合规,但有前提

同一个椭圆上连两条线到两个不同的 actor,是标准画法,它表示这两个角色触发并执行这个用例的方式完全一致(讲义原话 both will trigger and execute the use case in the same way)。

它不是「两个角色都会用到这个功能」—— 这两件事差很远。讲义接着给了反向判断:

create a separate use case for each of the actors if they are not using the use case identically

情况怎么画
两人用法一致(同一界面、同一套步骤)一个用例连两根线
两人用法不同拆成两个用例,哪怕名字听起来像
共用的是一整批用例、只是权限不同参与者泛化(空心三角子→父)

判据一句话:这两个角色点进去之后,看到的是同一个界面、走的是同一套步骤吗?

本例的对照:「客服」与「片区经理」看待派单的方式一样 → 可以连同一个用例;「客服派单」与「工程师接单」一个发起一个响应 → 必须拆成两个。

画这一笔:从第二个 actor 直接拖一条实线到这个已有椭圆即可。不要加箭头 —— 关联线表示 actor 主动触发;带箭头只在「系统主动推送」时才用。

4 活动图:符号 + 泳道

4.1 七个符号

元素搜索词说明
开始状态(start state)start实心黑圆,只能有一个
结束状态(final state)end黑圆外套一个白圆,可以有多个
动作(activity)rounded rectangle两端圆角的矩形,名字是动词短语
转移(transition)直接连线开放箭头的实线
判断(decision)decision菱形,分支处标 [guard]
同步条(synchronization bar)horizontal bar粗黑横线,表示并行分叉或汇合
泳道(swimlane)lane 或手画矩形竖直分区,顶部写角色

两个常被忘的细节:判断的 guard 要写在方括号里([yes] [no]),以及一个菱形可以有三条以上分支(讲义特意提了这一点,因为很多人以为只能二分)。

另外,讲义明确要求:这一阶段忽略异常。不要画「是否输入有误」「是否重复提交」这类校验分支,也不要画「操作成功」的确认框 —— 只保留业务决策。

guard 打在线上,不是文本框:双击连线的中间位置直接打字,得到的是「线的标签」,会跟着线走。如果用文本框单独摆,线一挪就跟标签分离了。

4.2 泳道:draw.io 里最别扭的一个

泳道在 draw.io 里不会自动吸附。两条路都可以走,各有代价:

做法优点缺点
用 lane(Pool / Lane 形状)顶部有标题带,看起来正规拖活动进去时容易变成「泳道的子元素」,整体挪动会连坐
手画矩形 + 竖分隔线完全自由,活动怎么摆都行移动时框不会跟着走,得手动调整

推荐手画矩形,理由很实际:考场上你要频繁改布局,泳道框如果吸附了活动,每次挪动都要重新解绑,反而更慢。

手画顺序也有讲究 —— 先排活动,最后画泳道框。因为活动位置定下来之后,泳道框只需要照着边界拉一次;反过来先画框,框一改就要重排活动。

4.3 含实体时的那一支箭头

题目写「include entities」时,多半是 8 分题,其中相当一部分分在实体上。做法是:

  1. 在图的右侧(或每条泳道内)画实体符号(矩形/类符号),写上实体名;
  2. 从动作连线到实体,标出这次操作用到了哪个实体;
  3. 方向取决于读还是写:
    • 读(查档案、取余额)→ 箭头由实体指向动作;
    • 写(更新状态、新增记录)→ 箭头由动作指向实体。

这一笔在 workshop 批改里被反复标成 Wrong access / Should be read。有个简单记法:数据流向动作 = 读,动作流向数据 = 写。如果实在分不清,在图旁边加一行文字注释说明「此步读取 WorkOrder」—— 至少不会因为符号歧义白丢分。

4.4 自查这张图

  • 只有一个开始状态?
  • 每个判断都有方括号条件?
  • 判断的每条出口都能走到结束状态(没有悬空分支)?
  • 泳道数量和角色数量对得上?
  • 实体画了,读/写箭头方向正确?

5 顺序图:把 basic flow 一行一行摊开

5.1 四个元素

元素搜索词 / 操作
对象/生命线(lifeline)搜 sequence 拖出预置组,或手画:矩形 + 竖虚线,写法 :ClassName
消息(message)连线的实心箭头,标消息名与参数
返回(return)虚线 + 开放箭头(讲义说「返回可以假定、不画也行」,但画了更清楚)
激活条(activation bar)生命线上的细长矩形,表示这段在处理

纵向就是时间,从上往下读。消息编号(1: 2: …)是可选的,但强烈建议画 —— 它让「我覆盖了 basic flow 的每一步」这件事一眼可见。

返回线怎么变虚线:选中消息线 → 格式面板 Line → 勾 dashed。或者 Edit Style 打 dashed=1;endArrow=open;。 激活条如果没自动出现:预置的 sequence 形状拖出来时自带,手画的生命线没有。直接拉一个细矩形叠在虚线上就行,不用找专用形状。

5.2 生命线怎么摆

分析模型的顺序图里,生命线的顺序基本是固定的:

text
: Actor  |  :Boundary(界面)  |  :Control(控制器)  |  :Entity…  |  :ExternalSystem

按这个顺序摆,消息箭头大部分从左指向右,交叉线最少。三类分析对象各自的职责不能串(笔记 22):

  • 边界对象(boundary) 只负责与外部交互:收输入、显示结果、对接外部系统。不做业务判断;
  • 控制对象(control) 负责协调流程:收到请求,决定交给谁,汇总结果;
  • 实体对象(entity) 承载数据与规则,通常对应到数据表。

一个很具体的判分点:「系统显示列表」这类步骤是两件事 —— entity 返回数据(虚线返回),boundary 负责显示(发给边界对象或标 display())。把显示画成 control 自己完成,是职责错位的典型。

5.3 外部系统是边界对象,不是实体

basic flow 里出现「系统把资料送给 Payment Gateway / 供应商库存系统」时,接收方要画成边界对象,不是实体。讲义给的判断很直接:你需要写代码去和它对接,那它是系统外部接口。

5.4 自查这张图

  • basic flow 的每个编号都至少对应一条消息?
  • 每个参与对象都有生命线头?
  • 四条生命线的顺序是 Actor → Boundary → Control → Entity?
  • 返回用虚线?消息用实线?
  • 「显示」这一步是由 boundary 做的,不是 control 自己完成?

6 类图:三格、五种符号、一个方向

6.1 类符号与可见性

元素写法
三格类名 / 属性 / 操作,从上到下
属性visibility name : type [= init],如 -name : String
操作visibility name(param : type) : type,如 +getId() : String
可见性- private、# protected、+ public

题目如果写「not required to define the attributes or methods」,就只画类名 + 关系,把时间省下来检查箭头。属性只对实体类定义(讲义明确说 boundary 与 control 不列属性)。

三格的横线不用画:搜 class 拖进去就是三格,横线自动生成。双击任意一格打字。 想把某一格留空?直接留空,别删线。 加构造型:双击类名上方,会出现一行 «»,填 entity / boundary / control。

6.2 五种关系的符号

关系符号落到 Java
dependency 依赖虚线 + 开放箭头方法参数、局部变量、返回值
association 关联实线(可带重数)字段持有引用
aggregation 聚合空心菱形(菱形在整体一侧)集合字段,元素由外部传入
composition 组合实心菱形(菱形在整体一侧)集合字段,元素在内部创建与管理
inheritance 继承实线 + 空心三角,指向父类extends

三个必查的地方:

  1. 菱形画在「整体」那一端,不是部分那一端;
  2. 空心三角指向父类,不是指向子类(这个每年都有人画反);
  3. 依赖用虚线,关联用实线。

6.3 重数写法

写法含义
1恰好一个
0..1零或一个
* 或 0..*零或多个
1..*一个或多个
4..64 到 6
2, 6..82,或 6 到 8

重数标在线的端点附近(靠目标类那一头)。draw.io 里双击线的端点位置打字即可。

6.4 分析模型里的关系限制

这一张表是从讲义里直接抄下来的,属于「画了就扣分」的类型:

想画的关系允许吗
同一构造型之间:关联 / 依赖 / 继承 / 聚合 / 组合都可以
不同构造型之间做继承无意义
不同构造型之间做聚合 / 组合一般无意义
boundary 直接关联 entity不推荐(中间应隔着 control)
actor 与 entity / control 直接关联不推荐(actor 只接触 boundary)

6.5 自查这张图

  • 菱形在整体那一端?
  • 空心三角指向父类?
  • 依赖是虚线、关联是实线?
  • 属性只出现在实体类上?
  • 类名是业务术语,没有 Table、DTO 这类技术后缀?

7 界面草图:4 分的题只要 3 样东西

界面草图不考画功,考的是「信息选对了没有」。三个必查项:

  1. 题目提到的每个角色,都能在图上找到他要的信息。题目说「让客服、工程师和仓管都能排期」,那至少要出现:工单列表、时段可用性、待办请求、配件库存;
  2. 隐喻明确标出。日历(排期)、看板列(状态流转)、红黄绿灯(紧急度)、地图(上门路线)都是可以用的隐喻。在图旁写一句「以周历隐喻呈现工程师可用时段」,否则阅卷人不知道那是隐喻还是随手画的格子;
  3. 一屏只有一个主结构。把三种隐喻堆在一起,既讲不清也扣分。

再加两个加分动作:给区块加标题(让主次一眼可辨),在图下写 3 行说明,逐条对上题目要求。

用哪套形状:draw.io 搜 wireframe,或 More Shapes 里勾选 Mockup / Wireframe。里面的 Button、Input、Table、Window 是够用的。 但 4 分题不建议花时间美化 —— 用普通矩形 + 文字,十分钟内画完,得分差别不大。

8 一张速查表:最容易画反的几笔

把上面所有「方向性」的规则抽出来,就是下面这张图。它按三张图分成三列,红字全是「画反就失分」的地方:

考场符号速查:左列是用例图的参与者、用例、系统边界与 include、extend、泛化三种关系的箭头方向;中列是活动图的开始与结束状态、动作、判断菱形、同步条,以及读实体和写实体两种相反的箭头;右列是类图的依赖、关联、聚合、组合、继承五种符号,并标出菱形贴在整体一端、空心三角指向父类

如果只想要文字版,就是下面十二行 —— 考前一晚过一遍就够:

#画什么正确方向画反的后果
1«include» 箭头基用例 → 被包含用例语义变成「被包含用例依赖基用例」,判错
2«extend» 箭头扩展用例 → 基用例与 include 混淆,整题失分
3泛化空心三角子 → 父继承方向反了,类图整题失分
4聚合 / 组合菱形菱形贴着整体那一端整体部分关系反了
5活动图 guard写在方括号里写成 extend 的裸条件,符号不规范
6extend 的条件不加方括号与活动图 guard 混用
7活动图读实体实体 → 动作被批 wrong access / should be read
8活动图写实体动作 → 实体同上
9用例图箭头只在「系统主动推送」时才画向 actor满图箭头,说明没理解触发方向
10顺序图返回虚线 + 开放箭头用实线会被当成新消息
11actor 与用例的线实线,actor 在边界外画进框内,边界失效
12依赖关系虚线用实线会被读成关联

9 工具与交付:别在最后十分钟翻车

讲义那句「know how to draw all the UML diagrams using online tool」是硬要求,因为答卷是电子稿。所以考前必须练熟三件事:

  1. 找到每个符号在哪。特别是 «include» / «extend» 的标注、空心菱形、实心菱形、空心三角 —— 这几个在多数工具里都藏在二级菜单(或者像这篇 §1.3 说的,要改端点样式);
  2. 改图要快。需求阶段改图是常态,工具里改一次要重画的话,考场上就会开始少改;
  3. 导出清晰。知道怎么导出 PNG(File → Export as → PNG,把 Zoom 调到 200% 以上),而不是截图。

图纸命名与呈现还有两条小事:每张图都要有标题(Figure 2: Activity Diagram – Process Home Repair),并且标明对应哪一小问。阅卷人找图的时间越短,越可能给到你应得的分。

本节自测

  1. 用例图里,什么时候才需要把箭头画向 actor?大多数线为什么不带箭头?
  2. include 和 extend 的箭头方向分别指向哪一方?extend 的条件写法与活动图的 guard 差在哪?
  3. 活动图里「读实体」和「写实体」的箭头有什么区别?为什么 workshop 会批 wrong access?
  4. 顺序图里「系统显示列表」这一步应该由几个对象完成?分别做什么?
  5. 聚合和组合的菱形画在哪一端?空心三角指向父类还是子类?
  6. 分析模型里,为什么 boundary 直接关联 entity 是「不推荐」的?
  7. 聚合、组合、继承这三种符号在 draw.io 的形状库里搜不到,该怎么画出来?
  8. 画活动图时,为什么建议「最后再画泳道框」?

参考答案

  1. 只有当用例先启动、去唤醒 actor 时才画箭头向 actor(定时器/传感器触发的通知、邮件、告警)。因为绝大多数交互是 actor 主动触发的,画实线就够;满图箭头反而说明没理解触发方向(§3.2)。
  2. include:基用例 → 被包含用例;extend:扩展用例 → 基用例 —— 两者相反。extend 的条件写在箭头旁、不加方括号;活动图的 guard 必须写方括号(§3.3 / §4.1)。
  3. 读:箭头由实体指向动作;写:箭头由动作指向实体。判分依据是数据流向 —— 数据流向动作=读,动作流向数据=写。画反会被批 wrong access 或 should be read(§4.3)。
  4. 两个对象:entity 返回数据(虚线返回箭头),boundary 负责把数据显示出来。画成 control 自己完成就是职责错位(§5.2)。
  5. 菱形永远贴着整体那一端(不是部分那一端);空心三角必须指向父类(不是子类)。这两笔是最常画反的(§6.2)。
  6. 因为 actor 只应接触 boundary,boundary 又不应做业务判断 —— 中间必须隔着 control 来协调。直连会把「谁能访问数据」这件事画乱(§6.4)。
  7. 它们不是独立形状,而是连线的端点样式:选中线 → 格式面板 Line → 选 diamond / block → 设 filled=0 或 1。也可以 Edit Style 直接写 endArrow=diamond;endFill=0;(§1.3)。
  8. 因为 draw.io 的泳道不会自动吸附活动框,先画框的话,一旦调整框的大小或位置,里面的活动就要重排。先排好活动、再照边界拉一次泳道框,返工最少(§4.2)。

术语表

术语中文一句话解释
notation符号体系UML 规定的图形元素写法
system boundary系统边界用例图上框住所有用例的矩形,actor 在框外
communication association通信关联actor 与用例之间的实线
include relationship包含关系每次必执行的公共步骤,箭头由基用例指向被包含用例
extend relationship扩展关系条件发生时才叠加的行为,箭头由扩展用例指向基用例
generalization泛化子级指向父级的空心三角关系
start state / final state开始 / 结束状态实心黑圆 / 黑圆套白圆
decision node判断节点菱形,分支处标方括号条件
guard condition守卫条件活动图分支上的方括号条件
synchronization bar同步条粗黑线,表示并行分叉或汇合
swimlane泳道按执行者划分的竖直分区
wrong access读写方向错误实体读写箭头画反,workshop 常见批注
lifeline生命线顺序图里对象的竖直虚线
message消息对象间的一次调用,实线箭头
activation bar激活条表示对象正在处理的时间段
return返回用虚线箭头表示的结果回传
visibility可见性-、#、+ 表示成员开放程度
dependency依赖虚线箭头,表示临时使用
association关联实线,表示长期持有引用
aggregation聚合空心菱形,部分可独立存在
composition组合实心菱形,部分随整体消亡
multiplicity重数关系一端可对应的实例个数
endArrow / endFill端点箭头 / 是否填充draw.io 里画菱形与三角的两个关键属性
Edit Style编辑样式draw.io 格式面板里直接写属性的入口
metaphor隐喻借真实世界形态组织界面信息
assumption假设信息不足时写明的前提

© 2026 HuanYu Blog

记录技术,也记录思考