ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

UML核心图解析:顺序图、协作图、用例图与类图考点辨析

UML核心图解析:顺序图、协作图、用例图与类图考点辨析

简介:这份UML试题合集面向正在学习统一建模语言、准备课程考试或梳理面向对象建模知识点的学生与开发者,围绕用例图、顺序图、协作图等核心图型组织题目与知识问答,帮助读者在练习中辨析交互图的时空侧重点和适用场景。压缩包仅含1个doc文件,约62KB,属于轻量级文字资料,适合直接检索、打印或对照复习,不包含课件视频等附加内容。内容覆盖顺序图与协作图的差别及优缺点、高内聚度、对象间可见性、领域模型与概念类识别、统一过程四阶段、增量开发、用况描述方式以及UML五类图等,题型含简答、选择与填空式问答。已有11276人学习,可用于课前预习、章节自测和考前查漏补缺,也能作为课堂讨论与作业参考答案的线索。

1. 从装修图纸说起:UML 到底在解决什么问题

装修过房子的人都遇到过这种糟心事:你跟施工队说“这里要通透一点”,对方理解成把墙砸了;水电、木工、油漆各干各的,最后插座被柜子挡得严严实实。软件开发现场的问题几乎一模一样——产品说“用户下单后通知仓库”,开发理解成下单前通知,测试又按第三种理解写用例。

UML(统一建模语言)就是软件行业那套约定好的图纸语言。它不写代码,只画图:用例图圈定系统该做什么、不该做什么;顺序图和协作图记录多个对象之间怎么来回传消息。搞懂这几张图,再看需求文档和设计评审记录,就不会只看到一堆方框和箭头。这份资料把常见考法整理成题库,正好拿来对照着把概念一条条钉死。

2. 顺序图与协作图:同一段对话的两种摆法

2.1 为什么同一个交互要画两张图

一个系统跑起来,本质上是若干对象互相发消息。用户点“提交订单”,界面对象把请求转给订单服务,订单服务再去问库存、问支付,最后把结果一层层往回传。这段过程如果只用文字描述,读的人得在脑子里自己排时间线,稍微复杂一点就乱了。

UML 给的解法是画交互图。有意思的是它给了两种:顺序图和协作图。两者语义上是等价的——描述的是同一批对象、同一批消息,理论上可以互相转换,不少建模工具里按一个快捷键就能从顺序图生成协作图,反过来也行。既然等价,为什么还要两种?

因为人的关注点不一样。顺序图像剧本,你从上往下读,谁先说、谁后说、说完了等多久,一目了然;协作图像一张组织关系图,你先看到有哪些角色在场、谁跟谁连着线,再顺着编号去看他们说了什么。同一段交互,一个偏时间,一个偏结构。这不是重复劳动,而是同一条信息的两种投影方式,就像一栋楼既有平面图也有剖面图。

弄明白这一点,很多考题就不难了:问“两者主要差别”,答的不是“一个画得出一个画不出”,而是“顺序图强调交互的时间顺序,协作图强调交互的语境和参与交互的对象的整体组织”。

2.2 顺序图怎么读:时间轴上的消息队列

顺序图的骨架非常固定。横向一排是参与交互的对象,每个对象下面拖一条竖直的虚线叫生命线,代表它在这段时间里存在。生命线上有一段段窄长的矩形,叫激活期或者控制焦点,表示这个对象正在处理某件事、等着某个结果。

消息就是横着的箭头。实心箭头的同步消息表示“我调用你,我在这儿等你返回”;空心箭头的异步消息表示“消息发出去我就不管了”;虚线箭头是返回消息,把结果送回去。纵向从上到下就是时间流逝的方向,越靠下发生得越晚。

拿一个下单场景举例,写成 PlantUML 大致是这样:

@startuml actor 用户 用户 -> 订单界面 : 提交订单 订单界面 -> 订单服务 : createOrder(订单信息) 订单服务 -> 库存服务 : lockStock(商品号, 数量) 库存服务 --> 订单服务 : 锁定成功 订单服务 --> 订单界面 : 订单号 订单界面 --> 用户 : 显示下单结果 @enduml

这段描述里,->是同步调用,-->是返回,箭头上的文字是消息名和参数。读图的时候注意两点:一是纵向顺序,lockStock一定发生在createOrder之后;二是激活期,订单服务那条窄矩形从头到尾没断,说明它一直在等库存服务回话。如果这里画成异步,激活期就该断开,因为发完消息它就去干别的了。

顺序图的优点是直白,缺点也很实在:对象一多,横向就撑得特别宽。十几个对象并排,一张图打印出来字比蚂蚁还小。而且它为了把时间关系摆清楚,在水平方向上占的地方太多,删改对象的时候还得重排整张图。

2.3 协作图怎么读:对象之间的空间组织

协作图换了个思路。它先把对象画成一个个小方块,散在图上,然后用实线把它们连起来,这条线叫链,代表对象之间可以互相发消息的通道。消息不画成箭头串时间线,而是贴着链写,前面挂一个编号。

编号是协作图的命门。因为图面上没有时间轴,读者只能靠编号判断先后:1是第一条消息,2是第二条;如果1下面还分了1.1、1.2,说明这是第一条消息执行过程中嵌套发出的子消息。所以那句常考的话要记住——在协作图中,是通过消息编号来表示消息的时间顺序的。

还是下单那个例子,协作图会画成:用户连着订单界面,订单界面连着订单服务,订单服务连着库存服务。链上依次标1: 提交订单、2: createOrder、2.1: lockStock、2.1.1: 锁定成功。你顺着编号读,时间关系就出来了。

它的好处是省地方、好改。要加一个新对象,拉一条线接上去就行,不用把整张图推倒重排;分支结构也比顺序图清爽,不会因为多一个判断就多出好几条竖直的线。代价是消息一多就乱:二十条消息挤在几条链上,编号写成3.2.1.4,读的人得拿笔在纸上做标记才理得清顺序。这也是它最典型的缺点——消息密集时难以表达消息之间的先后。

提示:别把协作图当成顺序图的“简化版”。它俩是并列的两种交互图,谁也不从属于谁,只是在表达侧重点上做了取舍。

2.4 两种图怎么选:一张对照表说清

实际画图的时候没必要两张都画,选一张能说清事的就够了。判断依据可以看下面这张表:

对比维度顺序图协作图
关注重点消息的时间先后对象的组织与协作语境
布局方式按时间纵向铺开按空间关系摆放
消息顺序表达纵向位置天然体现靠消息编号
增加对象横向变宽,需要重排拉线接入,比较轻松
分支较多时图面变宽,但顺序仍清楚分支少,结构更紧凑
消息密集时仍然可读顺序容易读乱
典型场景向他人讲清一次调用流程展示模块之间谁依赖谁

按这个表看:要给不熟悉系统的人讲清一次业务流程,顺序图更省口舌;要说明系统由哪些部件协作完成、某个对象的职责边界在哪,协作图更直观。

顺带提醒一个容易错的地方:SSD(系统顺序图)虽然名字里带“顺序图”,但它把整个系统当成一个黑匣子,只画外部参与者发进来的消息,不对系统内部结构与功能做描述。它和普通的顺序图不是一回事,不少人在这上面踩过坑,画着画着就把内部服务全展开,图就废了。

3. 用例图:先把系统的边界画出来

3.1 用例图里的三个基本零件

用例图是需求阶段最常被拿出来看的一张图,因为它回答的是最原始的问题:这个系统到底管什么,不管什么。

图上的零件就三类。第一类是参与者,通常画成火柴人,代表跟系统打交道的角色——可以是人,也可以是另一个系统。第二类是用例,画成椭圆,代表系统对外提供的一项完整功能,名字一般是个动宾短语,比如“提交订单”“查询物流”。第三类是关系,把参与者和用例、用例和用例连起来。外面再套一个大方框,框内是系统边界,框外是参与者,这条线一画,职责就切开了。

这里要拎清一个概念:用例是一个描述性的文档,描述的是一个参与者使用系统完成某个业务过程时的事件发生顺序。它描述的是系统的使用过程,也就是功能需求;它不描述系统内部怎么干活,只定义系统该承担什么责任、必须做什么。这句话经常被考,也经常被误解——用例不是“功能点清单”,一条“登录”写成一个椭圆就完事,那是功能列表;真正的用例背后得有一段可以讲出来的事件流。

正因为如此,用例描述才分档。最简单的是 Brief,一段话概括;中间档是 Casual,用几段文字把主要过程说清;最完整的是 Fully Dressed,按模板填前置条件、主成功场景、扩展场景、后置条件。下面这个模板是常见写法:

用例名称:提交订单 主参与者:注册用户 前置条件:用户已登录,购物车非空 主成功场景: 1. 用户确认收货信息与商品清单 2. 系统校验库存与优惠券可用性 3. 用户选择支付方式并确认 4. 系统生成订单,返回订单号 5. 系统锁定库存 扩展场景: 2a. 库存不足:系统提示缺货商品,用例结束 2b. 优惠券失效:系统提示并允许用户取消优惠券后重试

这段文本里,第 1 到 5 步就是“事件发生顺序”,扩展场景处理的是分支。写成这样,开发和测试才有得对。只画一个椭圆不写事件流,等于把需求留成了玄学,后面必然翻车。

3.2 include 与 extend:两种最容易写反的关系

用例之间的关系里,包含和扩展是最常考也最常写反的一对。

包含关系说的是:A 用例执行时,一定要执行 B。比如“创建新订单”和“更新订单”都需要检查用户账号是否正确,那么“检查用户账号”就是一个被包含的公共步骤,从这两个用例各拉一条带箭头的虚线指向它,箭头上标 include。判断标准很简单——被包含的那段,是每次都必须走的。

扩展关系说的是:A 用例执行到某个条件满足时,才可能去做 B。比如“下单”时用户可以选择使用优惠券,用券不是必须的,“使用优惠券”就是从“下单”扩展出去的用例,箭头方向是从扩展用例指向基础用例,标 extend。判断标准是——它带条件,可发生可不发生。

为什么容易混?因为两者在图上长得像,都是一条虚线箭头。区分诀窍有两个:一看方向,包含是基础用例指向被包含者,扩展是扩展用例指向基础用例;二问一句“每次都得走吗”,是就包含,不是就扩展。把这句话默念两遍,基本不会再错。

还有一对容易顺带搞混的是泛化。参与者之间可以有泛化,比如“VIP 用户”继承“普通用户”的行为;用例之间也可以有泛化,把几个用例的公共部分抽成一个父用例。泛化画的是空心三角箭头,和虚线箭头完全不同,看一眼箭头样式就能分辨。

3.3 用例图管边界,不管顺序

用例图最大的价值是把系统边界定下来,但它有个天然短板:它看不出先后。图上十几个椭圆并排放着,谁先谁后、谁触发谁,一概不知。

所以用例图从来不单独使用。写完用例、画完图,紧接着就得给关键用例配顺序图或者协作图,把事件流展开。常见的资料组织方式也是这样:先用用例图圈范围,再用交互图讲过程,最后用类图落结构。三张图各管一段,缺一段就有一段说不清。

4. 类图与领域模型:静态视图的骨架

4.1 类图描述的是什么

UML 的图可以粗分两大类:一类描述系统“长什么样”,一类描述系统“怎么动”。类图属于前者,它给的是系统的静态设计视图——有哪些类、每个类有什么属性和操作、类与类之间是什么关系。

类画成一个分三层的矩形:最上面是类名,中间是属性,最下面是操作。属性写成- 订单号: String这种形式,前面的符号表示可见性。类之间的关系有几种:关联是两者之间有连接,聚合是整体与部分但部分可以独立存在,组合是整体没了部分也没了,泛化是继承,依赖是一种较弱的使用关系。这些关系在图上用不同的线型区分,实线、空心菱形、实心菱形、空心三角箭头,画错一个符号,含义就变了。

类图常被拿来和对象图对比。类图是抽象的,描述“订单类应该有什么”;对象图是某一时刻的快照,描述“3 号订单这个具体对象现在属性值是多少”。包图则是把一堆元素打包装进一个命名空间,属于组织手段,不是新的语义。

4.2 高内聚度:一个类该背多少职责

高内聚度是对一个类中各个职责之间相关程度和集中程度的度量。这句话可以拆成两个可操作的判断:这个类干的活彼此相关吗?这个类的体量是不是大得离谱?两个都过关,才叫高内聚。

它其实包含两层意思。第一层,不要给一个类分派太多职责。一个类塞进二十个方法,横跨订单、支付、日志、导出,看着万能,实际上是没人敢动。第二层,履行职责时尽量把部分职责分派给有能力完成的其它类。不相关的职责不要分派给同一个类——这句是底线。

举个常见的糟糕设计:一个“订单”类里,既有计算金额的方法,又有发邮件通知的方法,还有生成 PDF 对账单的方法。这三件事的相关程度很低,任何一件改动都会牵动这个类,测试也难写。合理做法是拆成订单、通知服务、对账单导出三个角色,各管一摊。拆完之后每个类的职责集中,这才叫高内聚。

高内聚通常和低耦合配着说。耦合讲的是类与类之间的依赖程度,依赖越少越松散,改动的影响面越小。内聚讲的是一个类自己内部是否拧成一股绳。两个指标一起看,才能判断设计好坏:一个类内部啥都干,外部又跟十几个类纠缠,那基本就是灾难现场。

4.3 可见性:对象之间能不能“看见”

可见性指的是一个对象能够“看到”或者引用另一个对象的能力。通俗地说,A 想给 B 发消息,前提是 A 手里得有 B 的引用;拿不到引用,这条链就断了,图也画不下去。

在类图里,可见性用四个符号标在属性和操作前面:

符号含义谁能访问
+public任何对象
-private只有本类内部
#protected本类及子类
~package同一个包内

对象之间建立可见性的途径,常见的有几种:A 持有 B 的属性引用;B 作为参数传给 A 的方法;A 的方法里临时创建了 B;B 是一个全局可访问的对象。这几种途径在顺序图里体现得最明显——如果两个对象之间根本没有可见性,那条消息箭头就是画不出来的,硬画出来也是错的。

这一点在设计评审时特别有用。有人画了一张顺序图,A 直接调用了一个跟它八竿子打不着的对象,你顺着可见性一问,往往就发现是漏了一层中介,或者把两个层次的职责搅在了一起。

4.4 领域模型与概念类的找法

领域模型是一组表示真实世界的概念类,在设计工作中广泛用来启发设计软件对象。注意这句话的落点:它表示的是真实世界的概念,不是软件部件的模型。领域模型里不该出现“数据库连接池”“消息队列客户端”这类实现层面的东西,出现就说明跑偏了。

找概念类有两种常用方法。一种是概念类类别表,先列一批常见类别——人、地点、物品、事件、交易、角色、组织等,然后拿业务描述去对照,看能对上哪些。另一种是标识名词短语,把需求描述通读一遍,把里面的名词和名词短语圈出来,筛掉同义的、筛掉不属于问题域的,剩下的就是候选概念类。

建模步骤也不复杂:先列出候选概念类,再画出领域模型图,然后必要时加入概念类之间的关联,最后必要时加入概念类的属性。注意“必要时”这三个字——不是每个类都要有属性,也不是每两个类都要连线,画得越满不代表越完整,反而常常意味着没想清楚。

领域模型和类图最容易搞混的地方在于:领域模型只描述概念、属性和关联,不谈方法、不谈可见性、不谈实现。它是问题域的语言,类图是解决方案的语言。先有前者,后有后者,顺序倒过来就容易把实现细节提前焊死。

5. 易混概念:五组最容易搞混的图与说法

5.1 状态图与活动图

易混点:两者都能描述“变化”,图上的圆角矩形和箭头看起来几乎一样,很多人以为活动图就是状态图的简化版。

为什么混:这两张图确实都跟“流程”沾边,而且都属于行为图这一类,教材里常常挨着讲。加上活动图里也有“状态”这个词(活动状态),术语一重叠,脑子就糊了。

怎么区分:看建模对象。状态图盯的是单个对象,描述这个对象在生命周期里会经历哪些状态、什么事件让它从一个状态跳到另一个;活动图盯的是一串动作的流转,强调的是活动之间的控制流,可以有分叉、汇合、分支,还能用泳道按负责部门分组。一句话记:状态图回答“这个对象现在处于什么状态”,活动图回答“这套流程下一步做什么”。所以对反应型对象建模,用状态图;描述跨多个角色的业务流程,用活动图。泳道这个元素只属于活动图,看到泳道就可以排除状态图。

5.2 顺序图与协作图

易混点:有人记成“协作图是顺序图的一种特例”,或者反过来,认为协作图只是画法不同的顺序图。

为什么混:两者语义确实等价,工具里还能互相转换,转换完信息一点不少,于是给人造成“一个是另一个的变形”的错觉。

怎么区分:它们是并列的两种交互图,没有从属关系。顺序图按时间顺序布图,协作图按空间组织布图;前者用纵向位置表达先后,后者用消息编号表达先后;前者对象一多就横向撑爆,后者消息一多就编号难读。考试里问“哪个不正确”,凡是说“某图是某图的特例”的选项,基本可以直接划掉。

5.3 组件图与部署图

易混点:两者都跟系统的物理实现有关,都出现在设计的后半段,容易觉得是同一件事的两个名字。

为什么混:组件和节点都是“物理部件”这一大类里的概念,一个是软件层面的实现单元,一个是硬件层面的运行环境,中间隔着一层,不细看就分不开。

怎么区分:组件是系统中遵从一组接口且提供实现的物理部件,通常指开发和运行时类的物理实现,比如一个可执行模块、一个库文件;部署图描述的是节点以及节点上部署了什么,节点是运行时存在的物理元素,代表一台设备或一个运行环境。组件图回答“系统由哪些可交付的部件构成”,部署图回答“这些部件跑在哪些机器上”。组件图画的是部件和接口的依赖,部署图画的是节点之间的连接和部件在节点上的分布。

5.4 正向工程与逆向工程

易混点:两个词都带“工程”,方向感全靠一个“正”一个“逆”,不看定义很容易顺着语感记反。

为什么混:它们描述的是模型和代码之间的双向映射,方向正好相反,而“正向”这个词在别的语境里又常被理解成“从头做起”,干扰很大。

怎么区分:正向工程是通过到实现语言的映射,把模型转换为代码;逆向工程是通过从特定实现语言的映射,把代码转换为模型。记忆锚点是“从哪到哪”——模型到代码是正向,代码到模型是逆向。前者是设计驱动实现,后者是拿现有代码反推设计,常见于接手遗留系统时先补一张图。

5.5 用例图与领域模型

易混点:两者都在需求阶段产出,都从业务描述里提取信息,初学者常把它们当成同一份东西的两种画法。

为什么混:做需求时经常是先列名词再画图,两个动作挨得太近,产出的东西又都是“框加线”,视觉上相似度很高。

怎么区分:用例图圈的是系统边界和对外功能,关注“系统该做什么”,元素是参与者、用例和关系;领域模型描述的是问题域里的概念类以及它们之间的关联和属性,关注“业务里有哪些东西”,不含任何系统行为。一个偏行为视角,一个偏结构视角。判断方法很直接:图上如果出现火柴人和椭圆,那是用例图;如果全是概念名词和连线,那是领域模型。

6. 什么时候该画哪张图:三个判断和一个教训

图不是画得越多越好,画错图比不画更费时间。真要动手,可以先问三个问题。

第一问:我要说清的是“谁参与、系统管什么”,还是“内部怎么跑”?前者用用例图,后者用交互图和类图。第二问:如果要说清内部怎么跑,读者更关心先后顺序,还是更关心参与者之间的组织关系?关心顺序用顺序图,关心组织用协作图。第三问:我要描述的是一个对象的状态变化,还是一串跨角色的动作流程?前者状态图,后者活动图,有部门分工就加泳道。

把这三问压成一张表,大致是这样:

你想回答的问题该用的图典型误用
系统边界在哪,谁能用哪些功能用例图拿它当流程图,指望看出先后
一次调用里消息的先后顺序图对象太多硬画,图面挤成一团
对象之间怎么组织协作协作图消息几十条还硬用,编号读不明白
单个对象的状态流转状态图拿来描述多角色业务流程
跨角色的业务流程活动图忘了加泳道,看不出谁负责
系统由哪些部件构成组件图和部署图混着画,节点部件一锅炖
部件部署在哪些运行环境部署图把类图里的类直接堆到节点上

也有明确不该用的时候。需求还没定、边界还在吵,就先别急着画顺序图,画出来大概率要推倒重来;反过来,如果只是给一个人讲清某个类的字段,画一整张类图也是浪费,写几行代码更直接。图是沟通工具,不是交付指标,没人看的图等于没画。

说个我自己的教训。早些年做一次设计评审,我为了显得完整,一个下单流程画了顺序图、协作图各一份,还配了状态图和活动图。结果会上有人指着协作图问“第 7 条消息到底在第五条之前还是之后”,我盯着编号看了半天才反应过来,是我自己把嵌套编号写错了层。那份图后来被当成反面例子在组里传了很久。从那以后我每次画交互图之前都强制走一遍:先确定这张图是给谁看的、他最关心顺序还是结构,只画一张,画完顺着编号或时间轴自己默读一遍再拿出去。

这份资料把这些考点按图种归了类,顺序图、协作图、用例图、类图、状态图、活动图都有对应的题目和解析,正好用来检验自己是不是真的分得清。需要的话可以拿去,对着上面这几个判断逐条过一遍,比死记定义管用。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表