简介:这是一份软件工程课程设计配套资源,聚焦“智慧养老服务平台”的面向对象分析与设计(OOAD)部分,适合软工课设学生、UML建模初学者及需完成综合报告的高校本科生。文档按实验报告体例展开:先明确目的与要求,再围绕老人、家属、医护人员、管理员四类参与者划分用例,覆盖注册登录、健康中心、生活中心、紧急联系、家属通信、在线咨询、通知发布、用户管理;类图提炼用户、老人、身体信息、线上诊室、诊疗书等核心类及其属性、服务,结合实例解释聚合、组合、泛化、关联、依赖等关系;顺序图、状态图则展示紧急服务等核心交互的消息传递与时间顺序。资源包仅1个doc格式Word文档,共414KB,内容集中,下载即可阅读;已有103人浏览/学习,可作为快速建立对象模型、绘制规范UML图、撰写实验报告与答辩讲解的配套素材,尤其适合课设周期较短的读者。
1. 软件工程课设里的智慧养老平台:OOAD 不是画图,而是把需求翻译成可评审的模型
每年软件工程课设交报告前一夜,总有人抱着画到一半的 UML 图发呆——用例图画成了功能菜单、类图画成了数据表、顺序图画成了流程图,导师一句“类和类之间为什么是聚合不是组合”就能让整组人沉默。这份智慧养老服务平台面向对象设计与分析资源,解决的正是这个问题:老人、家属、医护人员、管理员四类参与者怎么拆用例,八个核心类之间的五种关系怎么判定,健康信息录入和更新这个核心行为怎么用顺序图和状态图表达。它不是给你一堆画好的图,而是给你一套“从需求文本到模型图”的完整推演过程,适合软件工程课设、课程答辩前突击,也适合刚接触 OOAD 的开发者照着理解 UML 建模思路。
2. 用例模型拆分:四类参与者和 7 条用例命名规则
2.1 老人与家属:先把“功能菜单”翻译成“用户目标”
很多课设报告的用例图第一眼看上去像系统功能树,这是最常见的翻车点。用例图的本质是“参与者通过系统达成什么目标”,不是“系统提供什么功能”。老人用户在这个平台里的目标很清晰:获取服务、保持联系、应对紧急情况。所以老人用例不是“登录”“查看”“管理”这种动词+名词的菜单罗列,而是“注册并登录平台访问个人服务”“查看通知公告”“管理个人账户”“与家属联系”“反馈健康数据并接收评估”“使用生活服务”“紧急联系家属或医疗服务”这七个完整目标。
写用例描述的时候,我一般会在每个用例下面补一个三步结构:前置条件、主流程、异常分支。比如“与家属通信”这个用例,前置条件是老人和家属都完成了绑定,主流程是老人发起文字聊天或语音视频通话,异常分支是家属不在线时系统提示留言或稍后重试。这一步看似多余,但答辩时导师问“这个用例的边界在哪”,你有文字描述兜底,不会卡壳。
家属用户的用例本质上是对老人用例的镜像和管理。老人能“与家属通信”,家属就有“与老人通信”;老人能“反馈健康状况”,家属就有“查看老人健康数据”;老人有“紧急联系”,家属就有“紧急响应”。这样的对称关系不是巧合,而是需求分析里角色职责划分的结果。家属还多了一层“安排生活服务”——代替老人点餐、安排出行,这说明家属的定位是“辅助者”,不是“使用者”,画用例图时把这种角色差异体现出来,评审印象分会好很多。
2.2 医护人员与管理员:后台角色的用例边界
医护人员和管理员是后台角色,用例划分的逻辑和前两类完全不同。医护人员的用例只有四个:登录系统、查看老人健康数据、回复健康咨询、更新健康评估。注意这里没有“管理健康数据”这种模糊表述,因为医护人员的权限是“查看+回复+评估”,不是“增删改查”。如果给医护人员也画一个“管理健康信息”的用例,就违背了角色的最小权限原则,答辩时容易被追问权限边界。
管理员是唯一拥有系统级操作权限的角色,用例覆盖用户管理、通知发布、在线咨询监督、健康数据维护、用户服务协助、异常反馈处理。这些用例的粒度比老人和家属粗,因为管理员面向的是系统整体运营,不需要拆到“修改某条健康记录”这种细粒度。管理员用例设计里最容易漏的是“处理用户异常反馈”和“协助用户服务”这两个,它们不是核心业务,但真实系统里必须有,把它们放进用例图说明你考虑到了运营侧的兜底场景。
2.3 用例命名与粒度:从一句话需求到可评审的用例描述
用例命名的规则其实只有一条:用“动词+宾语”表达可观察的结果,并且主语是参与者不是系统。老人用例写成“查看通知公告”是对的,写成“公告展示模块”就错了,后者是系统视角的功能名。命名词汇也要统一,同一个动作不要一会儿用“修改”一会儿用“更新”,比如老人个人信息用“更新”,健康信息用“设置”和“修改”,这个区分在类图方法定义里也能延续,保持全文一致。
粒度的判断标准是“这个用例能不能在 30 秒内讲完主流程”。能讲完,粒度合适;讲不完,拆小。比如“管理个人账户”这个用例,主流程就是更新资料和改密码,两步,粒度合适。如果发现一个用例描述里出现了“然后……同时……接着……”这种长链条,说明里面混了多个用例,拆开。一个方便的记忆方式是:老人七个用例、家属七个用例、医护人员四个用例、管理员七个用例,总共二十五个,每个都能一句话说清主流程,这份用例模型才算立住了。
项目资源里每张用例图都配了参与者说明和用例列表,对着图反推需求文本,你会发现每个用例都能在原需求描述里找到对应出处,这就是用例模型和上游需求的可追溯性。可追溯性不只在文档里有用,它也是你答辩时回答“这个用例哪来的”最硬的底气。
3. 类图设计:8 个核心类的属性、方法抽取与五种关系判定
3.1 从用例反推类:属性和服务怎么抽取
类图是 OOAD 从分析跨入设计的分水岭。用例图告诉你系统做什么,类图告诉你系统由什么组成。这个项目里类图部分一共抽出八个类:管理员、用户、老人、家属、身体信息、线上诊室、医护人员、诊疗书。这个抽取思路值得记一下——先找名词,再找名词间的归属关系。用户、老人、家属、医护人员、管理员来自参与者;身体信息、诊疗书来自用例描述里出现的数据对象;线上诊室来自咨询行为发生的容器。
类属性不能只列名字,要有类型意识。拿“身体信息”类举例:用户ID、年龄、性别、体温、心率、血压、血糖。这些属性在 Java 里对应 int、String、double 等类型,比如体温和血压用 double 或 BigDecimal,血糖因为涉及小数点后一位,也是浮点类型。课设评审不会要求你写出完整类型标注,但你在文本里把“属性类型”这个维度提出来,说明你想过这个问题,比直接贴一张图效果好。
方法抽取的原则是“行为跟着数据走”。老人能“查看健康信息”和“设置健康信息”,这两个方法就挂在老人类上,不挂在身体信息类上;医护人员能“修改健康信息”,这个操作也通过老人类或身体信息类的方法实现。“查看老人诊疗书”和“查看老人身体情况”挂在家属类上,“发送诊疗书”挂在诊疗书类上。判断方法归属时问一个问题:这个操作修改的是谁的数据、服务于谁的目标?答案就是方法应该放的地方。
下面这个 PlantUML 文本可以快速生成类图的骨架,我一般用它先把属性方法摆出来,再讨论关系,避免一上来就画箭头把思路带偏。
@startuml class 用户 { - 用户ID: String - 姓名: String - 年龄: int + 加入家庭() + 移出家庭() + 修改密码() } class 老人 { - 身体信息: 身体信息 + 查看健康信息() + 设置健康信息() } class 家属 { - 电话: String + 绑定老人() + 查看老人诊疗书() + 查看老人身体情况() } class 身体信息 { - 年龄: int - 性别: String - 体温: double - 心率: int - 血压: String - 血糖: double + 修改身体信息() } class 医护人员 { - 职称: String - 部门: String + 修改健康信息() } class 线上诊室 { - 诊室名称: String - 时间: String + 加入诊室() + 移出诊室() } class 诊疗书 { - 诊疗ID: String - 诊疗结果: String - 诊疗意见: String + 发送诊疗书() } 用户 <|-- 老人 用户 <|-- 家属 老人 "1" *-- "1" 身体信息: 绑定 @enduml这个文本里的<|--表示泛化(继承),*--表示组合关系。实际画图时我会检查两点:第一,继承关系有没有把公共属性放到父类里(用户ID、姓名、年龄这三个属性老人和家属都有,提取到用户类就没冗余);第二,组合和聚合符号别混用(老人和身体信息这里用的是组合,因为身体信息离开老人没有独立存在价值,它不是一个独立被其他角色复用的对象)。
参数说明:泛化箭头指向父类,组合菱形画在整体那一端,聚合菱形也是画在整体端但菱形是空心。这一条判断标准几乎每次答辩都会问,后面避坑章节我再展开。
3.2 五种关系的判定标准:聚合、组合、泛化、关联、依赖
五种关系判定是整个类图部分的得分点和失分点。判定标准可以压缩成一句话:泛化看继承,聚合看整体与部分的生命周期是否独立,组合看部分能否脱离整体单独存在,关联看类之间是否有稳定的连接(消息传递、参数引用),依赖看是否存在临时的使用关系。
具体到这个项目,用户与老人是泛化关系,老人是用户的子类,继承用户ID、姓名、年龄,同时扩展了健康信息管理能力。这个好判断,难的是聚合和组合的区分。用户与家庭是聚合:家庭包含用户,但用户退出家庭后仍然存在,生命周期独立,所以是空心菱形。老人与身体信息是组合:一份身体信息被创建出来后,只属于某一个老人,老人注销或删除账户,身体信息随之销毁,所以是实心菱形。这个区别用一句话记:聚合是“家里有人,人走了家还在”,组合是“手和身体,手离开身体就是标本”。
关联关系在这个系统里有四组:老人与身体信息(老人指向身体信息)、家庭与家庭成员(家庭指向成员)、线上诊室与医护人员(诊室指向医护人员)、诊疗书与医护人员(诊疗书指向医护人员)、管理员与用户(管理员指向用户)。每一组都要标方向,方向代表谁有主导权。管理员与用户这组最容易画反——应该是管理员指向用户,因为管理员可以查看和管理用户信息,用户看不到管理员信息,单向关联。方向错了,评审一眼就能看出来,而且这个问题在你后续做系统实现时会直接影响服务层接口设计。
依赖关系在这里只有一个典型场景:管理员调用发布通知接口。依赖是虚线箭头加<<use>>标签,表示管理员这个类在某个方法里“用了一下”发布通知接口,用完就释放,不存在长期持有。很多初学者把依赖画成关联,把临时使用画成属性持有,这个差别在代码层面也成立——依赖对应方法参数或局部变量,关联对应成员变量。
3.3 类图落地:关系方向与多重性约束
把八张类图合成一张系统类图时,最容易乱的不是关系类型,而是多重性标注。多重性就是“一个 A 对应多少个 B”,写在关系线的两端,常见写法是 1、1..、0..。这个项目里至少要写清楚三处:一个家庭包含多个用户(家庭端 1,用户端 1..);一个老人对应一份身体信息(两端都是 1);一个线上诊室至少有一名医护人员(诊室端 1,医护人员端 1..)。
多重性不是画图装饰,它直接决定代码里集合类型怎么写。一对一就用引用类型,一对多就用 List,多对多就要引入中间表或者中间类。你画类图时不标多重性,到了数据库设计阶段就得自己猜,猜错就是一次返工。
还有一个细节容易被忽略:类图里不是所有属性都要显示。用户类的“家庭”属性、老人类的“身体信息”属性、诊疗书的“诊疗结果”对象,这些应该在关系线上体现,而不是在一个类里塞另一个类的类型声明。属性表达“是什么”,关系线表达“和谁协作”,两类信息各归其位,类图才不会变成一张数据字典截图。
从这份资源里可以对照一个实操经验:类图先画属性方法骨架,再画关系线,最后补多重性。顺序反了,往往会出现关系线画到一半发现两个类之间根本没有消息传递路径,只能回头改图。这个顺序也值得写进你课设报告的过程描述里,它体现的是设计思路而不是“我画完了”。
4. 核心行为建模:健康信息录入与更新的顺序图、状态图怎么画
4.1 顺序图:从登录到用药提醒的 7 步消息序列
顺序图表达的是“某个时间段内,对象之间按什么顺序发消息”。项目资源里拆解的核心行为是健康信息录入和更新,整条链路涉及老人用户、系统前台、健康中心后台、医护人员、家属用户、每日活动记录六个对象,拆成七步:
第一步,老人用户登录系统进入首页,这是整个行为的前提;第二步,进入健康中心页面,发起在线咨询;第三步,老人描述健康问题或上传相关图片,比如伤口照片、检查报告图片;第四步,等待响应,响应时限在业务文档里写得很具体——半小时内首次响应,复杂问题二十四小时内详细解答;第五步,查看医护人员的回复,包括诊断建议、治疗方案推荐和用药提醒;第六步,选择将健康状况共享给家属用户;第七步,把用药量记入每日活动追踪管理。
画顺序图时我一般用生命线和消息编号组织结构。老人在最左边,接下来是系统界面、后台业务对象、医护人员、家属。消息编号按时间顺序标 1、1.1、1.2,同一个对象的内部操作放在一个编号下,方便看出嵌套调用关系。顺序图的标题不要写成“健康信息录入顺序图”这么笼统,要写成“老人用户在线咨询并同步家属的顺序图”,这样图的可读性直接提升一个档次。
顺序图的技术含量不在画得多花哨,而在消息的返回信息不能丢。比如老人提交健康问题后,系统不是简单把消息转发给医护人员,而是要返回一个“已提交成功”的确认;医护人员回复后,系统要把回复同步给老人端,同时还要更新健康评估数据。消息有去有回,图才是完整的交互链路;只画请求不画响应,顺序图就退化成物理流程图了。项目资源里附带的顺序图在这两步都有明确标注,照着对比能看出返回消息的写法。
4.2 状态图:健康信息在“编辑—入库—检测—异常”之间怎么迁移
顺序图讲对象间交互,状态图讲单个对象的状态变化。这个项目里最值得画状态图的对象是“健康信息”,因为它经历的阶段多且每个阶段都有业务动作。项目正文描述得很清楚:老人能输入体温、血压、血糖数值,描述身体不适症状,记录近期的饮食情况、运动状况和睡眠质量,并且可以随时更新。系统后台持续监测这些数据,一发现异常立即汇报。
把这段需求翻译成状态图,至少要有五个状态:登录态(系统已登录,可进入健康中心)、编辑态(信息正在录入或修改)、提交态(数据已保存到数据库)、监测态(后台检查是否异常)、结果态(正常则继续监测,异常则汇报情况)。迁移事件是“用户登录系统”“启动编辑”“录入有更新/无更新”“删除”“保存数据”“评估数据”。画状态图的关键是给每个迁移标上事件名,比如从编辑态到提交态的迁移事件叫“点击保存”,从监测态到结果态的迁移事件叫“后台定时扫描”。
一个常被问到的细节是:无更新和删除这两个分支怎么处理。无更新指的是老人打开编辑页但没有改动,这种状态迁移应该从编辑态退回查看态,不触发保存动作;删除则是老人主动删除某条健康记录,这个动作在状态图里要画成从编辑态直接到结果态的迁移。把这两个分支画出来,状态图的完整度就超过了大多数课设报告。
状态图的最初状态最好用实心原点标注,在登录态之前。最终状态可以在“数据已保存且监测正常”或“异常已汇报”处结束。另外状态图里不要画角色,它只关心对象状态,不关心谁触发了迁移,把参与者画进去又变成活动图了。
5. 避坑:UML 建模课设里最容易翻车的 5 个细节
5.1 用例图画成功能菜单
现象:用例图里的用例名称全是“用户管理”“公告管理”“数据管理”,一眼看过去像后台管理系统菜单。
原因:把系统功能模块当成用例,没有从参与者的目标出发。用例是“老人查看通知公告”,不是“公告管理”。
解决:把每个用例改写成“参与者+动词+宾语”的句式,主语必须是参与者。老人侧写成“查看通知公告”,管理员侧才写“发布通知公告”。按这个规则过一遍用例图,老人都能找出来哪些是功能残留。这个坑几乎每组都会踩,检查时一条条念出来就能发现。
5.2 聚合和组合箭头画反
现象:用户与家庭画成实心菱形组合,老人与身体信息画成空心菱形聚合,答辩被追问后改口又自相矛盾。
原因:没抓住生命周期这个判定标准。组合要求部分不能脱离整体独立存在,聚合允许部分独立存在。
解决:画每一条菱形关系前问一个问题:整体对象销毁了,部分对象还在不在?家庭解散了,用户仍然存在,所以是聚合;老人删除了,对应的身体信息数据就没有意义,所以是组合。代码层面组合关系通常在整体构造方法里创建部分对象,聚合关系则是从外部传入部分对象,两个时机不一样。
5.3 类图属性不标类型,方法不标参数
现象:属性只有名字没类型,方法只有名字没参数列表,整张类图看起来像流程图而不是设计模型。
原因:画图时只关注了“有哪些类”,没把类图当成代码的前置设计。
解决:属性至少标出关键类型,例如 String、int、double;方法至少标出参数和返回类型,比如“修改身体信息(体温: double, 血压: String): boolean”。类型标注尽量少用自定义类型,避免类图里出现一个没有定义的类。这个习惯能直接帮助后续编码,属性类型和方法的签名在编码时就是要落地的契约。
5.4 顺序图只画请求不画返回
现象:顺序图里对象之间的消息全是请求,没有一条返回,图形看着像一条单向箭头链。
原因:把顺序图画成了“谁调用谁”的调用链,忽略了交互中必须存在的响应消息。
解决:画完每一条请求消息后,问自己“这条消息发出去之后,调用方需要拿到什么结果才能继续”。老人提交健康信息,要返回“提交成功”;向医护人员发起咨询,要返回“咨询已受理”;查看健康评估,要返回评估结果。返回消息用虚线箭头画,与实线请求成对出现,整张图立刻显得完整。
5.5 状态图忘记画初始和终止状态
现象:状态图直接从“登录”画到“汇报情况”,没有初始状态标记,也没有终止状态,看起来像半截流程图。
原因:不清楚状态图的语法要求,或者只关注了业务步骤。
解决:状态图的起点必须是一个实心圆点,终点是实心圆点外加圆环。把登录之前的状态标记为初始,把异常已汇报或数据已保存标记为终止。两个标记一画,这张图就不再是活动图了。这属于白给分的点,检查时对着状态图看一眼就能确认。
6. 把模型变成可评审的交付物:一份实验报告从 60 分到 90 分的三个习惯
习惯一:把每张图对应的需求原文贴进去。用例图、类图、顺序图、状态图在报告里不是孤立存在的,评审老师看报告时最想问的是“这个图是从哪段需求抽出来的”。我通常会在每张图下面写一个图注,格式是“图 X 描述的是需求中‘老人可以通过平台与家属进行文字聊天、语音通话、视频通话’这一场景”,一句话把图和需求绑定。这个习惯成本极低,却能把整份报告从“画了四张图”提升到“分析并验证了需求”的层次。
习惯二:为每个核心类补一段职责说明,五个关系都做完交叉检查。类的职责说清楚“这个类在系统里负责什么、哪些操作会改它的状态”,关系说明写清“为什么是聚合不是组合、为什么方向是这样画的”。交叉检查的具体做法是:拿类图里的每一条关系去顺序图里找对应的消息,如果一条关系在顺序图里找不到任何消息传递,那就说明这个关系是多余的,或者你的顺序图没有覆盖完整;反过来,顺序图里的一段交互在类图里找不到对应的类或方法,说明类图有遗漏。我做完这个检查之后,发现健康信息的“修改身体信息”方法最初在身体信息类里没有定义,在顺序图里出现了“保存修改后的血压数据”这个消息,两边一对上,就补上了这个方法。
习惯三:答辩前预设追问清单,练习一页纸讲完核心链路。导师最爱问的三类问题是“用例和类是怎么对应的”“类和类之间的关系怎么来的”“顺序图和状态图的业务依据是什么”。我的练习方式是:先花十分钟把健康信息录入和更新这条链路完整讲一遍,然后随机抽一张类图关系问自己“如果导师问为什么这里是聚合,我该怎么回答”。答不上来的地方回去看需求原文,直到每一个关系都能用需求文本里的原话兜住。这个项目的核心链路恰好是“老人—健康信息—医护人员—家属—每日活动”这条闭环,一页纸画清楚这条闭环上的对象和消息,整份报告的骨架就立住了。
最后分享一个教训:我做这份实验时,最初把所有精力都花在把图画得好看上,结果导师只问了一个问题——这张类图里的“身体信息”为什么是老人组合出来的对象,而不是一个独立的、可以被多个角色复用的类?我当场愣了几秒。后来复盘才意识到,组合和聚合的差别不是画图符号对不对,而是你是否真的理解部分对象的独立性边界。从那以后,每画一个关系,我都在旁边用一句话写下“这个关系的生命周期依据”,答辩时基本没有再被问倒过。希望你也能把这一步做扎实,希望这份资源的拆解思路能帮到你。
本文还有配套的精品资源,点击获取