简介:本资源是一份聚焦UML核心建模技能的系统性试题汇编,专为软件工程专业学生、UML初学者及备考软考/课程设计的学习者设计,旨在帮助读者深入理解用例图、顺序图与协作图等关键交互建模技术,并夯实高内聚、可见性、领域建模、统一过程等基础概念。压缩包为单个62KB的Word文档(.doc),内容结构清晰,涵盖19道典型问答题与选择题,每题均附详细解析,如对比顺序图与协作图的布图逻辑与适用场景、辨析UP各阶段核心任务、拆解领域模型构建步骤等,兼具知识梳理与应试训练双重价值。资源已获11266人学习下载,内容源自一线教学实践,知识点覆盖全面、表述准确,可直接用于复习巩固、课堂讨论或考前冲刺。
1. 用例图+顺序图:UML面试/笔试里最常“埋雷”的两个图,90%的人栽在第3题的时序逻辑上
你不是不会画用例图,而是画完被问“这个参与者和系统边界怎么定?”就卡壳;你不是没画过顺序图,而是消息编号一多、自调用一出现、异步返回一嵌套,立刻分不清激活框谁先消、谁后消、谁该虚线、谁该实线。UML考试和面试从不考“UML是什么”,它只考三件事:能不能一眼识别图中隐藏的职责错配、能不能把模糊需求精准翻译成图元素、能不能在图与代码之间做双向校验。这份《UML试题大集合》不是题海,是按真实考场节奏编排的“踩坑对照表”——所有题目都来自近3年某高校软件工程期末卷、某公司技术岗初试真题、某认证模拟题库高频复现题。它覆盖了UML中唯一被反复加权考查的动态建模模块:用例图(需求入口)+顺序图(行为落地),而协作图、状态图等其他图,全作为对比项穿插在真题解析中。适合两类人:一类是下周就要交课程设计文档、必须手绘规范图的学生;另一类是已写过Spring Boot但画不出订单创建完整时序、被面试官追问“为什么这里用同步调用而不是事件驱动”的开发者。拿分关键不在画得多美,而在每条消息背后是否能说出触发条件、失败分支、对象生命周期归属——这才是阅卷人和面试官真正盯的点。
2. 用例图:不是画圆圈和连线,而是用“参与者-用例-关系”三要素锁死需求边界
2.1 用例图核心三要素:谁在用?用什么?怎么用?
用例图本质是需求过滤器。它不描述“怎么做”,只回答三个问题:谁(Actor)在系统外发起动作?系统提供哪些可验证的业务价值单元(Use Case)?这些单元之间如何被复用或扩展(关系)?
- 参与者(Actor):必须是系统外部的、有明确目标的角色。常见错误是把“数据库”“日志服务”画成参与者——它们是系统内部组件,不是主动发起者。正确做法是追问:“这个角色有没有独立目标?它是否在系统边界之外?它是否通过接口与系统交互?”
- 用例(Use Case):必须是用户可感知的、完成一个完整业务目标的黑盒功能。例如“创建订单”是合格用例,“验证邮箱格式”不是——它是子步骤,应封装在用例内部逻辑里。
- 关系(Relationship):只有三种合法关系:关联(Actor ↔ Use Case)、包含(< >)、扩展(< >)。其中包含关系表示强制复用(如“创建订单”必须包含“检查用户账号”),扩展关系表示可选增强(如“支付”可扩展“发送短信通知”)。
2.2 高频真题:用例间关系辨析与纠错
真题1(某公司2023校招笔试):
在“在线教育平台”用例图中,“学生”可执行“选课”、“提交作业”、“查看成绩”;“教师”可执行“发布课程”、“批改作业”、“录入成绩”。其中,“提交作业”和“录入成绩”均需先“验证学生身份”。请指出图中应如何建模“验证学生身份”,并说明理由。答题思路:
- 先排除错误选项:不能将“验证学生身份”画成独立用例并让“学生”和“教师”都关联——这违反“用例必须由单一Actor发起”的原则(教师不发起验证,是系统在流程中自动触发)。
- 锁定关系类型:因“验证学生身份”是“提交作业”和“录入成绩”执行前的强制前置步骤,且无条件发生,故必须用
<<include>>关系。- 画法规范:在“提交作业”和“录入成绩”两个用例旁,分别画带箭头的虚线指向“验证学生身份”,线上标注
<<include>>。注意箭头方向是从主用例指向被包含用例。真题2(某高校2024期末考):
判断正误:“用例‘重置密码’可扩展‘登录’用例,当用户连续输错密码3次时触发。”答题思路:
正确。这是典型的<<extend>>关系场景:
- 基础用例:“登录”本身可独立完成(输入账号密码→验证→成功/失败);
- 扩展点:在“验证失败”分支后设置扩展点(如“密码错误次数≥3”);
- 扩展用例:“重置密码”仅在此条件下插入,不影响“登录”的主流程完整性。
关键提示:<<extend>>的箭头必须从扩展用例指向基础用例,且需在图中注明扩展条件(如“[密码错误≥3次]”)。
2.3 易错点:用例图里最常翻车的5个细节
错在哪 → 为什么错 → 怎么答对
① 把“系统管理员”画成两个Actor(如“后台管理员”和“数据库管理员”)
错因:混淆角色与职责。UML中Actor代表目标一致的用户群体,而非技术岗位。只要两者都通过同一管理后台操作用户数据,就应合并为一个“系统管理员”Actor。
答对法:追问“他们使用系统达成的终极目标是否相同?”——若都是“维护用户数据一致性”,则必为同一Actor。② 用例命名用动宾短语却含实现细节,如“用JWT验证Token”
错因:用例名必须面向业务价值,而非技术方案。“验证Token”是开发细节,“保障登录安全”才是用户目标。
答对法:强制用“动词+业务名词”结构,且动词需是用户可感知的动作(如“登录”“下单”“退订”),禁用“调用”“生成”“加密”等技术动词。③ 在用例图中画出类名、方法名或数据库表(如“User表”“checkPassword()”)
错因:用例图是需求层抽象,属于完全不涉及实现的黑盒视图。一旦出现代码级元素,直接判定概念混淆。
答对法:牢记口诀——“图中只见人和事,不见类与方法”。所有实现细节应留在类图、顺序图中体现。④ 将“发送邮件”“记录日志”作为独立用例与Actor关联
错因:这些是系统内部支撑动作,非用户主动发起的业务目标。用户不关心“邮件是否发送”,只关心“密码是否重置成功”。
答对法:用例必须满足INVEST原则中的“I(Independent)”——可独立交付价值。若删除该用例,用户核心目标无法达成,则它是主用例;否则是子活动,应放入<<include>>或顺序图中。⑤ 用例间用泛化关系(三角箭头)连接,如“支付”泛化出“微信支付”“支付宝支付”
错因:UML标准中,用例间的泛化关系极少使用,且仅适用于同一Actor下存在明确的“父用例-子用例”继承语义(如“用户注册”泛化出“学生注册”“教师注册”,且子用例有专属字段)。支付方式差异属于策略模式实现,应在设计阶段用类图表达。
答对法:优先用<<include>>复用公共流程(如“支付验证”),具体渠道选择作为用例内部分支处理,或在顺序图中用alt框标注。
3. 顺序图:时间轴是假象,对象生命线才是真相,90%的失分源于激活期画错
3.1 顺序图四要素:谁在场?何时活?传什么?谁响应?
顺序图是动态建模的“时间切片”,但它的灵魂不在时间轴,而在对象生命线(Lifeline)与激活期(Activation Bar)的严格对应。四要素缺一不可:
- 对象(Object):矩形框+下划线(如
:OrderService),代表运行时实例。注意::OrderService≠OrderService类,前者是后者的一个具体对象。 - 生命线(Lifeline):对象下方的虚线,表示对象在交互过程中的存在周期。生命线从对象创建开始,到对象销毁结束。
- 激活期(Activation Bar):生命线上方的窄矩形,表示对象正在执行某段逻辑(同步调用期间)。长度代表执行耗时,位置代表起止时刻。
- 消息(Message):带箭头的水平线,分三类:
- 同步消息(实线箭头):调用方阻塞等待返回,接收方激活期必须覆盖调用期;
- 异步消息(开箭头):调用方不等待,接收方激活期可晚于消息发出时刻;
- 返回消息(虚线箭头):仅当需要强调返回值或异常时显式绘制,日常可省略。
3.2 高频真题:从需求文本到顺序图的完整推演
真题1(某认证2023模拟题):
“用户提交订单时,系统需:① 校验库存;② 若库存不足,返回错误;③ 若充足,则冻结库存、生成订单、扣减库存、发送通知。” 请绘制核心对象(User、OrderController、InventoryService、OrderService、NotificationService)的顺序图。答题思路(分步拆解):
Step 1:确定对象创建时机
:User作为Actor,生命线从图顶开始,不创建对象;:OrderController由Web容器初始化,生命线全程存在;:InventoryService、:OrderService、:NotificationService均为单例,生命线全程存在(无需create消息)。Step 2:梳理消息流与激活依赖
User → OrderController: submitOrder() OrderController → InventoryService: checkStock() InventoryService → OrderController: [success] OrderController → OrderService: createOrder() OrderService → InventoryService: deductStock() OrderService → NotificationService: sendNotice()注意:
deductStock()是OrderService对InventoryService的二次调用,其激活期必须在OrderService激活期内;sendNotice()是异步操作,用开箭头。Step 3:绘制关键激活期
OrderController激活期:从submitOrder()开始,到createOrder()返回结束;InventoryService激活期:分两段——第一段响应checkStock(),第二段响应deductStock();OrderService激活期:覆盖createOrder()和deductStock()调用;NotificationService激活期:仅在sendNotice()期间存在。Step 4:标注关键分支
在InventoryService返回后,用alt [stock < required]框标注错误分支(返回错误给OrderController),用else框包裹后续正常流程。
3.3 易错点:顺序图里最致命的5个激活期错误
错在哪 → 为什么错 → 怎么答对
① 激活期起始点画在消息箭头起点,而非接收对象生命线上
错因:激活期属于接收方对象,必须从消息箭头落点处开始。若画在发送方箭头起点,意味着发送方在调用时就进入执行态,违背同步调用逻辑。
答对法:口诀——“箭头落到哪,激活从哪起”。用尺子比对:消息箭头末端坐标 = 激活期顶部坐标。② 异步消息(如MQ发送)后,接收方激活期立即开始
错因:异步调用中,消息发出后接收方不一定立刻执行(可能排队、延迟、失败重试)。其激活期应始于消息被实际消费时刻,而非发出时刻。
答对法:异步消息后,接收方生命线上不画即时激活期;待下一个同步消息(如消费者回调)触发时,再画激活期。或用note标注“消息入队,稍后处理”。③ 自调用(self-call)激活期与外层激活期重叠但未嵌套
错因:对象调用自身方法时,新激活期必须完全包含在外层激活期内,形成“俄罗斯套娃”结构。若平铺绘制,等于否认方法调用栈深度。
答对法:自调用消息箭头从本对象生命线发出并返回本对象,新激活期矩形必须严格位于外层矩形内部,且顶部对齐调用点。④ 返回消息(虚线箭头)未对齐到调用消息的激活期底部
错因:返回消息代表处理完成,其终点必须落在接收方激活期结束处。若画在中间,暗示逻辑未执行完就返回,属严重语义错误。
答对法:返回消息箭头末端 = 接收方激活期底边中点。若省略返回消息,则接收方激活期底边即为隐式返回点。⑤ 对象销毁后仍画出消息箭头(如
:OrderService执行完createOrder()后销毁,却仍有→ NotificationService消息)
错因:对象销毁(X标记)后生命线终止,不能再参与交互。常见于误将“服务停止”理解为“本次请求结束”。
答对法:单例对象永不销毁;临时对象(如DAO)仅在方法内创建,其生命线从create消息开始,到方法返回时结束(画X)。所有消息必须在生命线存续期内发出。
4. 协作图 vs 顺序图:不是二选一,而是用空间换时间的战术切换
4.1 协作图的本质:对象关系网 + 消息流拓扑
协作图(现称通信图)是顺序图的“空间视角”孪生兄弟。它不按时间排序,而是以对象布局反映系统静态结构,用消息编号标注时序。核心价值在于:
- 快速定位对象协作瓶颈:若某对象(如
:DatabaseConnection)周围消息编号密集(1.1, 1.2, 1.3, 2.1, 3.1),说明它是高耦合中心节点; - 验证对象职责分配:若
:UserService同时处理“密码加密”“邮件发送”“日志记录”,消息编号虽有序,但职责明显发散,暴露低内聚问题; - 支持增量修改:新增对象(如
:CacheService)只需在图中添加节点并连消息,无需重排整条时间轴。
4.2 高频真题:根据顺序图反向生成协作图的关键转换规则
真题(某高校2023实验考):
已知订单创建顺序图中,:OrderController依次向:InventoryService(消息1)、:OrderService(消息2)、:NotificationService(消息3)发送同步消息。请绘制对应协作图,并说明消息编号规则。答题思路:
Step 1:布局对象
将四个对象按协作紧密度排列::OrderController居中(协调者),:InventoryService与:OrderService左右相邻(核心业务),:NotificationService置于右下角(辅助服务)。避免直线排列,体现空间组织意图。Step 2:绘制消息与编号
:OrderController→:InventoryService:标1: checkStock();:OrderController→:OrderService:标2: createOrder();:OrderService→:NotificationService:标3: sendNotice();
关键规则:编号按消息首次发出时间排序,而非接收顺序。即使:OrderService在:InventoryService返回后才启动,其发出的sendNotice()仍标3(因它是第三条被发出的消息)。Step 3:补充返回消息(可选)
若需强调返回值,在消息旁加: [return],如1: checkStock() : [success]。但协作图通常省略返回,因编号已隐含时序。
4.3 易错点:协作图里最容易被忽略的3个空间语义
错在哪 → 为什么错 → 怎么答对
① 消息编号写在箭头线上,而非箭头旁空白处
错因:UML规范要求编号必须紧邻箭头末端,且与消息文本同行。写在线上会遮挡箭头,破坏“消息流向+时序”双重信息。
答对法:编号与消息文本作为整体,置于箭头末端右侧,保持最小间距(约1字符宽)。② 对象间无直接关联却强行连线(如
:User与:NotificationService直连)
错因:协作图中连线代表对象间存在关联关系(Association),即代码中存在成员变量引用(如OrderController.notificationService)。若无此引用,消息需经中介对象转发(如:OrderController→:OrderService→:NotificationService)。
答对法:画线前必查——Java中是否有private NotificationService notificationService;?若有,则直连;否则必须通过持有该引用的对象中转。③ 消息编号跳跃或重复(如1, 2, 4, 5 或 1, 1, 2)
错因:编号必须严格递增且连续,反映消息发出的绝对时序。跳跃说明遗漏消息(如忘记画:InventoryService返回:OrderController的确认);重复则混淆时序。
答对法:按顺序图时间轴从上到下,为每条发出消息(非返回)分配唯一编号。用铅笔先标号再连线,避免返工。
5. UML与其他开发环节的衔接:从图到代码的3道生死关卡
5.1 用例图 → 需求规格说明书:如何把“包含关系”翻译成验收标准
用例图中的<<include>>不是绘图装饰,而是可测试的契约。例如“创建订单”包含“检查用户账号”,必须转化为:
- 前置条件:用户已登录且Session有效;
- 后置条件:若账号无效,返回HTTP 401,响应体含
{"error": "invalid_session"}; - 测试用例:
TC-001:Session过期时提交订单 → 断言状态码=401,响应体包含error字段;
TC-002:Session有效时提交订单 → 断言状态码=200,响应体含order_id。
若用例图未定义这些,需求文档即不合格。
5.2 顺序图 → 接口定义:消息参数如何映射为API契约
顺序图中每条消息都是API设计蓝图。例如:OrderController → :OrderService: createOrder(orderDTO: OrderDTO):
- 消息名
createOrder→ Spring MVC@PostMapping("/orders")方法名; - 参数类型
OrderDTO→ 请求体JSON Schema(需定义userId,items[],address等字段);
{ "userId": "string", "items": [{"productId": "string", "quantity": "integer"}], "address": {"street": "string", "city": "string"} }
- 返回值(隐含在激活期结束)→ HTTP 201 Created + Location header 指向
/orders/{id}。
若顺序图未标注参数类型,接口文档必缺失字段约束,导致前后端联调崩溃。
5.3 协作图 → 微服务拆分:消息流向如何暴露服务边界
协作图中跨对象的消息,就是微服务间的RPC调用点。例如:OrderService→:InventoryService: deductStock():
- 服务边界:
InventoryService必须独立部署,提供POST /inventory/deduct接口; - 数据一致性:因是同步调用,需考虑分布式事务(Saga模式)或最终一致性(发库存扣减事件);
- 容错设计:
OrderService必须实现InventoryService不可用时的降级逻辑(如返回“库存检查中,请稍后”)。
若协作图中
:OrderService直连:Database,则违反微服务原则——数据库必须私有,只能通过InventoryServiceAPI 访问。
6. 答题技巧:用“三问定位法”秒杀90%的UML主观题
面对一道UML分析题,别急着画图。先用三问在脑中过一遍,答案自然浮现:
6.1 第一问:这个图在解决什么层次的问题?
- 用例图→ 锁定“谁要什么”(需求层);
- 顺序图→ 拆解“谁在何时让谁做什么”(设计层);
- 协作图→ 审视“谁和谁必须在一起”(架构层);
- 类图→ 定义“每个东西长什么样”(实现层)。
若题目问“如何改进系统可维护性”,答用例图毫无意义——必须指向协作图(减少对象间耦合)或类图(提升内聚、降低耦合)。
6.2 第二问:图中哪个元素违背了单一职责?
这是UML题的“黄金钩子”。看到任何对象:
- 检查它接收的消息是否超过3种业务类型(如
:UserService同时处理登录、发邮件、记日志); - 检查它发出的消息是否指向5个以上不同对象(如
:OrderController直连库存、订单、通知、支付、物流); - 检查它是否同时承担“决策”(if/else)和“执行”(调用DAO)——这暴露控制类与实体类职责混杂。
答案模板:
“:XXX违反高内聚原则,因其同时承担【A职责】与【B职责】。建议将【B职责】提取为独立对象:YYY,原对象仅保留【A职责】,并通过<<include>>或消息调用复用。”
6.3 第三问:如果删掉这个图,开发会卡在哪?
- 删用例图→ 需求范围失控,开发不知道“用户到底要什么”;
- 删顺序图→ 接口联调地狱,前后端对“谁先调谁”永远扯皮;
- 删协作图→ 微服务拆分随意,数据库被多个服务直连,事务一致性崩塌。
这问直击UML存在价值。答案必须绑定具体开发痛点,例如:
“若无顺序图,OrderService与InventoryService的调用时序无法对齐,导致超卖(库存扣减晚于订单创建)”。
从那以后我每次画UML图,都强制走一遍这三问:先定层次,再揪职责,最后问代价。哪怕只剩30秒检查,也能揪出那个藏在角落的<<include>>漏画,或是:OrderService激活期没包住deductStock()的致命错误。希望帮到你。
本文还有配套的精品资源,点击获取