简介:一份面向统一建模语言(UML)初学者与软件工程实践者的配套教学资源,围绕《UML基础、建模与设计实战》整理而成。资源共45个文件,压缩包大小4.63MB,由13个PPT课件、12个UML工程文件、14个Java源码及6个辅助文件组成。PPT课件覆盖UML概述、面向对象基础、建模工具简介、用例图、类图、顺序图与协作图、状态图与活动图、组件图与部署图以及统一软件过程RUP等核心知识,章节按从理论到实战的路径递进;UML工程文件和Java示例对应汽车租赁、图书管理、BBS论坛、新闻中心、数码录音机等典型业务场景,可直接打开建模工程查看完整模型,并对照源码理解从需求分析到系统设计再到代码实现的落地过程,部分案例演示了完整项目的目录结构与代码组织。已有484人学习,适合结合课件系统入门、自学或培训教学参考,并按项目案例逐步练习UML建模与设计实战。
1. 一套能跟着动手的UML课件,解决的是“画了图但没用”的问题
很多人学UML最大的痛苦不是记不住图标,而是图例都懂,一到自己项目里就不知道画什么、画到什么程度。这套《UML基础、建模与设计实战》课件与配套例子,恰恰把重点放在“从需求文本到完整模型”的推导过程上,而不是逐个语法点的罗列。它适合三类人:准备毕业设计、需要画系统建模图的学生;刚转岗开发、要参与设计评审的工程师;以及团队里被要求“先把图补上”但不知道图怎么来的产品和技术负责人。我最初拿到这套课件时,觉得例子有点老,读进去才发现,真正的价值在于它每组图都配了需求原文和建模决策,能看出每个元素为什么存在。这篇笔记就按我自己的学习路径来拆:先看三件套图的推导顺序,再讲例子怎么练,最后说清楚踩过的几个坑。
2. 把UML三件套看透:用例图、类图、时序图的建模顺序与选择标准
UML一共十几种图,日常设计真正高频使用的就是用例图、类图、时序图这三张。它们回答的问题完全不同:用例图回答“系统为谁提供什么价值”,类图回答“职责和数据如何沉淀”,时序图回答“一次交互中消息怎么流转”。只有把这个先后顺序固定下来,建模才不会变成无脑画框。
2.1 为什么建模顺序影响后面所有图的正确性
我见过不少同学一上来就画类图,画到一半发现用例都没理清,类图推倒重来。顺序错是UML实践中最高频的翻车原因。正确的顺序是从需求文本出发,先圈定参与者和用例,再根据用例里的名词和动词提炼候选类,最后挑核心业务场景画时序图验证交互。换句话说,前面的图是后面图的输入条件,而不是装饰品。
这个顺序不是教条,而是为了减少返工。用例图定义的是系统边界:哪些事情系统做、哪些事情参与者自己做。边界没定清楚,类图就会把不该系统管的类也设计进来。类图又决定了时序图中消息的接收者是谁,如果类关系错了,时序图的消息路径自然也对不了。我一般会要求自己在画下一张图之前,先能口头解释上一张图里每个元素的来源。
下表是我现在给团队做设计评审时用的职责对照表,新同学照着这个表格自查,基本能避免顺序混乱。
| 图类型 | 回答的核心问题 | 典型产出物 | 常见误用 |
|---|---|---|---|
| 用例图 | 谁用系统完成什么目标 | 参与者、用例、边界 | 把功能菜单当用例 |
| 类图 | 系统里有哪些职责和数据 | 类、属性、方法、关系 | 把数据库表结构直接搬上来 |
| 时序图 | 一次操作中消息按什么顺序发生 | 生命线、消息、激活条 | 把流程图画成时序图 |
2.2 从用例图提炼系统边界:三个必填元素与常见画法
用例图看上去最简单,反而最容易被画浅。一个合格的用例图必须包含三类元素:参与者、用例、关系。参与者是在系统外部、与系统交互的人或系统;用例是参与者通过系统完成的一个完整目标;关系则包括关联、包含、扩展和泛化。
判断一个节点是不是用例,就看它是否回答“参与者能从中获得什么可感知结果”。比如登录不是一个完整用例,因为登录本身不产出业务价值,它的价值是支撑“下单”和“查订单”。课件里的例子有一个很好的做法:把每个用例都写成“动词+宾语”的形式,例如“提交请假申请”“审批报销单”,而不是写“登录系统”“数据维护”。这个习惯能逼着建模者从业务视角思考问题。
画图本身没有太多技术含量,真正的难点在于确定用例的粒度。粒度太粗,一个用例能拆成十个流程;粒度太细,图变成功能列表,评审时没人看得下去。我的经验是:先写主成功场景,如果主成功场景超过十步,说明用例组合得太粗;如果用例只有一个系统操作就能完成,说明细到功能级了。课件里给出的粒度参考是多数字例保持在五到八步主场景,这个尺度比较适合业务系统。
2.3 类图不是画表结构:关联、聚合、组合怎么选
类图是整套课件里篇幅最大也最容易画跑偏的部分。常见错误是把类图画成数据库表结构,每个类只贴属性,关系全部画成一根线。类图的本质是表达职责分配和对象间的结构性关系,属性远没有职责重要。
关系选择上,关联、聚合、组合三者的边界让很多人头疼。我的判断规则很朴素:如果两个对象只是临时认识,生命周期互不约束,用关联;如果一个是整体、一个是部分,且部分可以脱离整体独立存在,用聚合;如果整体销毁时部分必须一起销毁,用组合。举个例子:订单和订单项是组合关系,订单没了订单项没有存在意义;客户和订单是关联关系,订单删了客户还在;部门与员工是聚合关系,部门解散员工仍然存在。
课件例子中值得学习的另一个点是:关联关系的两端应该标注多重性。多重性不是数据库外键约束,而是业务规则。我以前常常漏掉“一个客户可以拥有零到多个订单”这一端的 0..*,后果是后续设计接口时参数是单对象还是列表判断不了。类图上每一个多重性标注,都是给后面时序图和代码落地的输入条件。
2.4 时序图验证职责分配:消息序号与生命线的阅读顺序
时序图不是流程图。流程图的箭头表示控制流,时序图的箭头表示消息传递。阅读时序图必须先看生命线顶部的对象,再看消息序号。消息序号表示时间维度的先后,同一条生命线上的激活条表示对象处理消息的时间范围。
时序图最大的价值是验证类图里的职责分配是否合理。我一般会选一个核心用例,把用例描述中的每一步映射成一条消息,消息的接收者就是类图里承担职责的那个类。如果某条消息找不到合适的接收者,说明类图漏了职责;如果某个类在一张时序图里接收了超过五条消息,说明它职责过重,需要考虑拆分。
课件里有一个我印象很深的点:返回消息也用虚线箭头画出来,但返回消息不占用独立的业务步骤。很多初学者把“查询订单信息”的返回也当成一个步骤去画,导致消息序号混乱。正确的做法是把交互动作和返回数据分开看,交互动作需要设计,返回数据只是结果传递,不需要专门设计一条处理逻辑。
3. 跟着课件例子练建模:从需求描述到用例图与类图的推导路径
课件最有操作性的部分,是每一章都给了需求原文和最终模型图。这部分如果只当成“看图识字”就浪费了。正确练法是把它当成作业来对照,自己先画一遍,再和课件例子找差异。下面是我总结的四步练习路径,每一步都有明确的输入和输出。
3.1 例子文件怎么读:先看需求文本还是先看图
大多数人的坏习惯是先看结论图,再回头找需求里对应的地方,结果是看懂了图却练不出建模感觉。我在带新同学时,强制要求先做两遍需求阅读:第一遍通读,把需求里的参与者圈出来;第二遍精读,给每个动词标注发生位置是系统内部还是外部。做完这两步再看图。
对照时不要只看“像不像”,要逐项问三个问题:图里的参与者是不是都来自需求文本;用例是否覆盖了需求中的完整业务目标;每个用例的主成功场景是否能在需求原文中找到依据。课件例子里的图并不完美,有的地方甚至和需求文本存在细微出入,但正是这些出入能帮你建立批判性的读图能力。你可以把疑问记在便签上,然后再看作者的建模思路表达。
如果只看不练,很快会陷入“眼睛会了手不会”的状态。我的习惯是每个例子至少隔一天再做第二遍,第二遍只凭记忆重画类图,画完再对照,这时才能暴露出自己是否真的理解了关系选择,还是只是照着抄了一遍。
3.2 用场景动词找用例:一套可操作的推导清单
把需求文本变成用例图,最稳的做法是动词驱动。步骤不复杂,按顺序执行即可:
- 读完整需求,圈出所有描述业务动作的动词,例如提交、审批、退回、撤销;
- 去掉系统内部自动执行的动作,例如校验、计算、日志记录,这些不是用例;
- 去掉登录、退出这类纯技术性动作;
- 把剩余动词按“参与者+目标”组合成用例名称,例如“员工提交请假申请”;
- 为每个用例写两到三行主成功场景,验证它是否有独立价值。
执行完这套流程,通常能产出一个比手工脑补可靠得多的用例清单。我检查过很多份初级建模作业,大部分漏掉的用例都集中在“撤回”“取消”“超时关闭”这种逆向流程上。需求文本里但凡出现“如果用户放弃”“超过期限自动”这类描述,都要追问是不是独立用例,或者当前用例的扩展分支。
课件例子里有一组订单处理的图,主用例是“提交订单”,扩展用例里有“取消订单”和“订单超时关闭”。这两个扩展用例如果漏掉,后续画状态图时必然发现缺少转移事件,最后还得回头补用例。这个教训我在项目X里踩过一次,现在凡是涉及状态流转的需求,我都会先回用例图核对一遍。
3.3 把用例转换成候选类:名词筛选与边界判断
用例图完成后,下一步是找候选类。方法同样是文本驱动:把需求文本中的名词全部圈出来,然后按照三条规则筛选:
- 是否在多个用例中出现;
- 是否同时具备属性与行为;
- 是否承担独立业务职责。
满足两条以上才能成为候选类,只出现一次且没有行为的名词,大概率只是某个类的属性。比如“收货地址”通常只是客户的属性,“订单项”则因为承担金额计算职责而成为独立类。
边界判断里最容易翻车的是把“订单”和“订单项”合并成一个类。表面上省了图,但订单项需要保存购买时的快照信息,而订单主体管理的是状态与支付信息,两者生命周期不同。课件例子用组合关系明确表达了两者的绑定关系,而不是用一个类硬包。另一个典型问题是“用户”和“管理员”的关系,很多人画成两个互不相关的类,实际上它们共享登录、头像、密码等基础属性,用泛化关系更合理。
候选类确定后,我会额外做一步:把每个类对应的用例编号写在类旁边。这一步看起来多余,但评审时别人问“这个类为什么要存在”,你能直接回答它是为了支撑哪个用例,比讲一堆设计原则更有说服力。课件例子的类图里虽然没有标这个信息,但我建议所有练习者自行补上这套映射记录。
3.4 用表格记录模型决策:为什么这么建模
对照课件例子时,会发现同一个需求可以有完全不同的建模方案。课件给出的方案不一定最优,但它是一套自洽的方案。真正拉开建模水平差距的,不是图画得漂亮,而是能否解释清楚每个决策的理由。
我设计了一张模型决策记录表,每次完成一个例子就填一张。表格长这样:
| 决策对象 | 备选方案 | 选择方案 | 理由 | 代价 |
|---|---|---|---|---|
| 客户与订单关系 | 关联 / 聚合 | 关联 | 生命周期相互独立 | 查询时需要显式关联 |
| 订单项归属 | 属性 / 组合类 | 组合类 | 需要保存快照并参与计算 | 类数量增加 |
| 取消订单 | 扩展用例 / 状态分支 | 扩展用例 | 有独立前置条件和主流程 | 用例数量增加 |
填表的过程能逼着你把“我觉得”变成“因为所以”。课件里凡是让我产生质疑的设计点,我都额外查了资料再填表,有的填完发现自己的方案有问题,有的填完发现课件方案确实更简单。这种对照练习比单纯补画十张图有效得多,因为模型错误的成本不在画图时,而在后续编码和变更维护时。
4. 从静态模型到动态模型:状态图与活动图的实战起点
用例图和类图解决的是“系统有什么”,动态模型解决的是“系统怎么运转”。在课件覆盖的动态图里,状态图和活动图是最容易被误用的两张,一个讲对象生命周期,一个讲业务流程流转,看名字就能选错。
4.1 状态图只画关键对象的生命周期,不是所有类都画
状态图的正确使用范围非常窄:只画那些状态复杂、状态数量大于等于三个、且状态转移受外部事件驱动的核心对象。订单、审批单、任务、设备这类对象适合画状态图;客户、地址、日志这类对象画了纯属浪费。
画状态图要准备两张表。第一张是状态表,列出对象可能处于的所有稳定状态;第二张是事件表,列出触发状态转移的事件。状态必须是稳定的、可观察的,“处理中”是稳定状态,“支付完成等待回调”不是状态,是转移过程的中间态。事件则必须来自外部,如“用户点击支付”“系统收到回调”“管理员执行驳回”。
我一般先画状态表再画事件表,顺序不能反。状态没想清楚就画转移线,最后图会乱成一团麻。课件里的订单例子,状态表是“待支付、已支付、已发货、已完成、已取消”,事件表是“提交订单、完成支付、确认发货、确认收货、取消订单”。对照着看就明白,状态图是先列表再连线。
状态图完成后,需要回查用例图确认完整性。凡是用例描述里出现“如果超时”“如果用户取消”这类分支,对应的事件必须出现在状态图上。这个地方是建模中最容易漏的,我放在后面第 5 章专门讲。
4.2 活动图用于梳理业务流程分支,别和流程图画混
活动图和流程图长得像,但使用场景不同。流程图适合表达单一线程的处理步骤,活动图更强调分支、并发与参与者泳道。在业务系统设计中,当流程涉及多个角色协作,或存在并行执行的任务时,活动图是不二选择。
我判断是否需要活动图的规则很简单:流程中是否出现“同时”“分别”“多个人都能发起”这类表述。例如“订单出库时同时扣减库存并通知物流”就适合用活动图的分叉汇合;而“校验参数好再查询数据库”这种顺序处理用流程图画清晰得多,画成活动图反而显得夸张。
课件里活动图例子不多,但给出的分配泳道示范值得学。每个泳道代表一个参与者或一个系统模块,活动符号落在哪个泳道,就表示哪个角色负责执行。这个泳道信息是流程图里没有的,它能直接暴露职责分配是否合理。我在项目评审中发现,如果某个泳道承接了太多活动,说明该模块职责过重,需要返回到类图层面重新分配。
4.3 课件里“订单”“审批”类例子的状态机怎么抽象
订单和审批是状态图教学中最经典的两个例子,课件里给的状态不多,但覆盖了完整生命周期。下面是我根据课件思路整理的简版订单状态模型,可以直接作为模板套用到类似业务:
| 状态 | 进入事件 | 离开事件 | 动作 |
|---|---|---|---|
| 待支付 | 提交订单 | 完成支付 | 记录创建时间 |
| 已支付 | 完成支付 | 确认发货 | 冻结库存 |
| 已发货 | 确认发货 | 确认收货 | 扣减库存 |
| 已完成 | 确认收货 | 无 | 生成评价入口 |
| 已取消 | 取消/超时 | 无 | 释放库存 |
抽象这套模型时,最需要关注的不是正常链路,而是每个状态下的“异常出口”。待支付状态要支持取消,超时未支付要自动关闭;已发货状态如果用户申请退款,是否需要增加退款状态。需求文本里这些分支往往都写得模糊,需要建模者主动找产品确认。
如果你从零开始建状态机,我建议按三遍法来检查:第一遍只画正常链路,第二遍补充取消、退回、超时分支,第三遍对着用例图逐用例核对,看每个用例的扩展场景是否都有对应事件。三遍走完,状态图基本能覆盖核心业务规则。
5. UML建模实战中的五个常见坑与排查方法
这部分内容来自我给团队做设计评审和带教时的真实踩坑记录。每一条都是“现象、原因、解决”三段式,读的时候可以先对号入座,再按方案去改。
5.1 用例图画成了功能菜单
现象:用例图里出现了“用户管理”“数据维护”“系统设置”这种名词性节点,评审时没人能说出它们分别给用户带来什么价值。
原因:建模者把系统模块划分直接搬到了用例图上,以为用例就是功能入口的集合。实际上用例必须是一个完整的业务目标,功能这个词本身不具备业务语义。
解决:把每个功能菜单反推成业务故事。例如“用户管理”要拆成“创建用户”“停用用户”“重置密码”三个用例,每个用例都能写出参与者、主流程和业务规则。检查时用一个问题自测:如果需求变更导致这个功能删除,用户是否感知不到任何业务损失?能感知到才配叫用例。
5.2 类图出现大量无意义的getter/setter
现象:类图里每个类都堆着十几个属性,属性下面是清一色的get与set方法,图看着很“完整”,但评审时完全无法讨论业务行为。
原因:很多人把数据库表字段直接翻译成类属性,再把IDE自动生成的getter/setter抄进图里。类图因此退化成表结构图,丢失了职责设计信息。
解决:类图画的是职责,不是字段清单。属性只保留业务上需要关心的,方法只保留有业务逻辑的。如果需要展示对外接口,可以单独用方法列表表达;如果属性只是承载数据,连画都不必画。我在自己的设计规范里规定:类图出现超过六个纯getter/setter方法直接扣评审分。
5.3 时序图消息方向与返回值混淆
现象:一张时序图里,消息箭头乱飞,查询操作返回的数据也被画成独立步骤,消息序号从 1 排到十几,没人能看出来一次交互的骨架是什么。
原因:时序图的每种箭头都有明确语义:实线箭头是同步消息,虚线箭头是返回消息。很多初学者把返回数据当成一条新消息,导致消息激活条错乱,时序图退化成程序调用堆栈。
解决:画时序图时先只画请求消息,把所有返回虚线统一放在目标交互完成之后,且不计入消息序号。检查时看两条规则:每条激活条必须由一个外部输入触发;每个消息的接收者必须是类图中真实存在的类。如果接收者在类图里找不到,说明类图漏类或时序图画错。
5.4 状态图漏了“取消”“超时”这类外部事件
现象:状态图只画了“提交、通过、完成”这条光明大道,没有“取消”“驳回”“超时关闭”的分支。项目上线后运营反馈“用户订单取消不了”,排查半天发现状态机压根没建模这个转移。
原因:需求文本里正常链路写得很详细,“如果...”开头的分支常常只有一句话,建模时被忽略。等到代码阶段用 if 语句补分支,状态模型已经存在缺口。
解决:状态图画完后,用事件驱动法做穷举。把需求里所有可能的用户操作、定时任务、外部回调列成事件清单,逐个事件过一遍:当前状态收到该事件后应该转移到哪个状态,不允许出现“不做处理”的模糊答案。我通常把事件清单做成表格,一项项打勾,用这个办法堵住漏分支的老问题。
5.5 图与代码同步失效,最后图成了摆设
现象:设计图评审通过后没人更新,三个月后代码重构了一次,图还是旧版本。新同事照着图理解系统,越看越糊涂,最后图彻底失去参考价值。
原因:把图画当成“上线前的一次性交付物”,而不是持续维护的活文档。UML的投入产出比是长线效应,不维护的图比没有图更有害,因为它会制造错误的权威感。
解决:把图纳入代码评审流程,涉及类关系变更时同步更新类图和时序图。我见过一个有效做法,是在代码变更的模板里增加一项“是否影响设计模型”,勾选“是”就必须附带更新后的图。这个机制虽然不能消灭所有同步问题,但能把图腐烂的速度压到可控范围。
6. 把课件例子改造成自己的建模模板:一个可复用的验证清单
学完课件里十几个例子后,最值得做的一件事是提炼一套属于自己的建模验证清单。每次画完一组图,按清单逐项过一遍,能挡掉八成基础错误。下面是我的清单,你可以直接抄去改:
- 用例图的每个用例是否都是“动词+宾语”结构,且能说出参与者获得什么价值;
- 是否漏掉了取消、超时、退回这类逆向分支;
- 类图中每个类是否能找到至少一个支撑它的用例;
- 关系端点的多重性是否标注完整,能否讲清楚业务含义;
- 时序图中每个消息的接收者是否能在类图中找到对应类;
- 状态图中每个状态是否都有明确的进入事件和离开事件;
- 是否有一个状态存在多个同名事件产生歧义,例如两个事件都叫“确认”。
我自己平时还会加一条:把整套图从头讲一遍给别人听,讲的过程里凡是卡壳的地方,基本都是隐藏的设计缺口。曾经在一次模拟项目X的设计评审里,我讲到订单状态图时突然想不起来“已支付”状态下超时未发货会怎样,翻需求原文才发现产品根本没定义这个分支。这种问题靠看图自查很难发现,但靠讲述能逼出来。
现在拿到任何一套旧系统要做重构设计,我的做法是先花半天把用例图和类图补起来,再挑三个核心用例画时序图和状态图,然后跑一遍上述清单。这套流程就是从课件例子里练出来的,它把UML从画图工具变成了设计思维。如果你照着练完前五章的内容,建议挑一个自己最熟悉的业务场景,尝试只画用例图和类图来建模,不需要一步到位,哪怕先画两张图都比不画强。我也曾因为嫌麻烦跳过用例图直接画类图,后来在评审中被连续追问几个关系选择为何如此设计,回答不上来,只好回头补用例,那章图画了三遍才校准。现在我把这些血泪经验固化成了上面的清单,希望帮到你。
本文还有配套的精品资源,点击获取