简介:这份文档是航空订票系统UML建模设计的完整方案,可供软件工程课程设计、毕业设计或系统开发前期的建模参考。内容围绕订票模块、航班信息管理模块和个人信息管理模块展开,依次给出需求分析、用例图、类图、状态图、顺序图与合作图,并用用户用例图、管理员用例图、顶层用例图区分不同角色权限,同时细化各类状态和交互过程,能够帮助读者快速掌握UML多种图形的绘制思路与规范表达。资源包内有1个docx文档,容量约535KB,内容结构完整,适合需要完成类似建模作业或撰写设计文档的读者直接对照参考。目前已有1622人学习下载,认可度较高。文档正文详细描述了系统需求、用例规约、模块划分和核心图形设计,既可作为课堂作业的参考模板,也可作为项目开发前期的需求梳理与设计蓝本,具有较强的实用性和借鉴价值。
1. 航空订票系统 UML 建模设计:一份能从答辩到开发都接得住的交付文档
做课程设计最怕的不是写代码,而是把设计文档写成流水账。航空订票系统是课程设计和毕业设计里出现频率极高的一类业务系统,但很多人一上来就画用例图,画完用例图画类图,画完类图画时序图,最后画的东西彼此对不上,答辩时被问一句"这个用例的前置条件是什么"就卡住。
这份航空订票系统 UML 建模设计文档,核心价值不是几十张图,而是把"需求、角色、用例、类、交互"五个层次串成了一条完整链。游客、注册用户、管理员三类角色边界清晰,14 个用例规约带前置条件和异常事件流,类图与用例对应,时序图和协作图能互相印证。对正在做课程设计、毕设或者需要快速了解 UML 建模全流程的人来说,这是一份可以直接当作骨架来补全的参考资源。
2. 需求与角色权限拆解:三类参与者、两个验证门槛和一个容易被忽略的游客边界
2.1 三类参与者的权限边界:游客只能看首页,用户才能订票,管理员要二次验证
航空订票系统的需求原文里有一句话很关键:浏览用户被划分为游客与用户,未注册用户只能访问系统首页,首页提供登录功能和前往注册按钮。这意味着系统最外层就有一道硬边界——游客连航班查询页都进不去,所有业务操作都发生在登录之后。
很多人在画用例图时会把游客当成一个完整的参与者,给它分配注册、登录两个用例,这在语义上是矛盾的:游客一旦发起注册,他的身份就已经在向注册用户转换,而不是以游客身份执行用例。更合理的做法是把注册和登录放在一个独立的认证用例集合里,参与者标注为"未注册用户/注册用户"或"所有访问者",业务用例才区分普通用户与管理员。
权限边界再往下一层是管理员。原文特别强调了一个容易被忽略的设计点:管理员登入系统时与普通注册用户相同,但进行敏感操作时,比如点击航班信息添加或修改,需要进行身份验证,此时需要输入由系统最高权限的管理员派发的标识符。这是一个典型的二次身份验证场景——普通登录只证明"你是管理员",敏感操作需要再次证明"你有权限执行该操作"。
在设计文档里,这种二次验证不应该只写在需求描述里,而应该落到用例规约的前置条件和基本事件流之中。比如"添加航班信息"用例的前置条件不只是"进入添加航班信息页面",还应该写明"通过管理员标识符验证"。否则画类图时,Admin 类的这个方法到底需不需要独立权限校验,开发阶段就会左右摇摆。
表 1 是本文档中三类角色与功能权限的完整对照,这个表在你写需求说明书或者做评审 PPT 时可以直接引用。
| 角色 | 可访问页面/功能 | 权限说明 | 涉及用例 |
|---|---|---|---|
| 游客(未注册用户) | 系统首页,登录,注册 | 不能查询航班、不能订票 | 注册,登录 |
| 注册用户 | 航班查询,机票预订,已定机票查询,退票,修改已定航班个人信息,查看个人信息,修改个人信息,打印票据 | 可以操作自身订票链路,但不能管理航班信息 | 用例 1-10 |
| 系统管理员 | 航班信息增删查改,统计订票数据,查看/修改个人信息 | 普通登录后,敏感操作需二次标识符验证;不能以管理员身份代替用户订票 | 用例 11-14 |
2.2 三大功能模块与用例映射:先有模块划分,才有用例清单
原文把系统划分为三个模块:订票模块、航班信息管理模块、个人信息管理模块。这个划分顺序非常符合 UML 建模的思维习惯——先做业务域划分,再从每个业务域里找用例,最后按参与者归类。
订票模块是核心,包含查票、订票、退票、改票功能,对应用例图中的航班查询、机票预订、已定机票查询、退票。值得注意的是,原文的用例清单里出现了"修改已定航班个人信息"和"打印票据"两个容易被漏掉的用例。前者解决的是订票后旅客联系方式和证件信息变更的问题,后者给线下值机或报销场景留了出口。这两个用例对评审老师来说是非常好的提问点:修改已定航班个人信息和修改个人信息的区别是什么?前者约束的是已生成订单关联的快照信息,后者修改的是账户基础档案。如果不用用例规约去区分清楚,开发时数据库就会出现"改了用户表却不知道要不要同步订单表"的迷惑。
航班信息管理模块属于管理员专属模块,包含添加航班信息、修改航班信息、删除航班信息、统计订票数据。统计订票数据这个用例在大多数类似设计里容易被弱化成一句"点击统计按钮",后面第 3 章会专门讲怎么补强它。
个人信息管理模块在顶层用例图中与订票管理、航班信息管理并列,包含查看个人信息、修改个人信息。注册用户和管理员都涉及这两个用例,只是数据范围不同。
实际建模时,建议先画一张顶层用例图,只画三个大椭圆(订票管理、航班信息管理、个人信息管理)和两个参与者(注册用户、系统管理员),再分别展开角色级用例图。分层的好处是评审时先看整体边界,再钻细节,不会一上来被十几个用例淹没。
3. 用例图与用例规约:十四份规约里藏着半套表单校验逻辑
3.1 三层用例图结构:顶层定边界,角色层定权限,明细层定流程
这份文档的用例组织方式非常标准,分为顶层用例图、用户用例图、管理员用例图三层。顶层用例图只放三个业务模块和两类参与者,用来表达"系统能干什么、谁在用";角色用例图把每个参与者能触发的用例展开;真正写代码和测试用例时,用的是每个用例对应的用例规约。
为什么要这么分层?只有一个用例图塞满 14 个用例,图面会非常拥挤,而且参与者与用例之间连线交叉,评审很难一眼看出游客边界和管理员二次验证的关系。分层之后,每个图都只回答一个问题:系统边界在哪、某个角色能做什么、某个具体功能的完整流程是什么。
从这份文档的 14 个用例清单可以看出,作者对"角色—用例"的归属是做过推敲的。比如"修改已定航班个人信息"放在用户用例图里,而"修改个人信息"同时出现在用户和管理员的用例图里;"统计订票数据"只出现在管理员用例图里。这种粒度分配带来的直接好处是,后续从用例规约反推页面和数据库时,不会出现"每个页面到底是谁在用"的模糊地带。
提示:如果你在画自己的用例图时拿不准某个用例该归给谁,就反问一句"这个操作的执行者是谁、受益者是谁、数据归属是谁"。比如统计订票数据的执行者和受益者都是管理员,就不该出现在普通用户的用例图里。
3.2 用例规约逐条核对:从基本事件流和异常事件流里提取校验规则
用例规约是这套设计里信息密度最高的部分。以用户注册为例,原文规约的基本事件流只有三步:用户点击注册按钮、用户提交注册信息、系统完成注册。但异常事件流里给出了三条明确提示:未输入用户名、未输入密码、两次密码输入不同。
这三条异常流翻译成开发语言就是三组表单校验规则——用户名必填校验、密码必填校验、密码一致性校验。表 2 展示了常见课程设计里"注册页面"应该实现的校验项来源,全部可以从这份规约中直接提取。
| 异常事件流描述 | 校验规则 | 对应前端行为 | 对应后端接口约束 |
|---|---|---|---|
| 系统提示未输入用户名 | 用户名必填 | 表单提交前检查字段非空 | 服务端再次校验,防绕过前端 |
| --- | --- | --- | --- |
| 系统提示未输入密码 | 密码必填 | 提交前检查密码字段非空 | 密码字段不允许 NULL 或空串 |
| --- | --- | --- | --- |
| 系统提示两次密码不同 | 两次输入一致 | 提交前比对两个密码字段 | 服务端比对加密前明文 |
航班查询用例的异常流更有意思——"未输入查询条件时,系统提示请输入查询条件"。很多初稿里航班查询默认是"进入查询页就列出全部航班",但这个异常事件流暗示的是另一个交互逻辑:查询页必须带条件才能触发检索,空条件不返回全量数据。这在答辩时是个容易翻车的点,评审如果问"查询条件为空时系统返回什么",照着这份规约回答就有据可依。
另外,第一期规约里"退票"用例的异常事件流写的是"用户未订任何机票,系统提示未订任何机票",这里存在一个措辞瑕疵:状态应该是"用户没有任何已预订且未出发的机票",而不是"未订任何机票"。如果照搬规约写代码,会漏掉"已付款但已过期航班"这类边界。拿到文档后,这类细节建议自己按业务常识补一版更严谨的描述。
3.3 一个偏弱的用例:统计订票数据该怎么补强
14 个用例规约里,"统计订票数据"是最单薄的,原文里它的规模只有"点击统计按钮、查询所有相关信息、进行统计"三步。放到真实系统里,这一步至少应该拆出三个要素:统计维度(按航班、按日期区间、按航线)、统计指标(订票数、退票数、营收)、统计输出的形式(表格还是图表)。
如果要把这个用例补成答辩能用的版本,我会在基本事件流里增加"用户选择统计维度与时间范围,系统按条件聚合订票记录并返回统计结果",在异常事件流里增加"所选时间范围内无订票数据时,系统提示暂无数据而非返回空表"。这样既能让类图里的统计方法签名有据可依,也能让后续数据库设计的 GROUP BY 条件直接对应上用例步骤。
4. 静态与动态建模:类图、时序图、状态图、协作图怎么串成闭环
4.1 类图核心设计:五个实体类的职责划分与关联关系
原文的类图部分给出了系统级的静态结构,参与角色包括用户类、管理员类、航班信息类、机票类、个人信息类。由于原文档中的类图为图形文件,属性与方法细节没有以文本形式展开,这里按课程设计中最常见的做法补全一版类图设计思路。
表 3 是本系统最核心的五个类及其职责、关键属性、关键操作,可以直接作为画类图的参照。
| 类名 | 职责 | 关键属性 | 关键操作 |
|---|---|---|---|
| User | 注册用户的账号与登录凭证 | userId, username, password | login(), register(), viewPersonalInfo() |
| Admin | 管理员的账号信息与权限标识 | adminId, empNo, authToken | login(), addFlight(), modifyFlight(), deleteFlight() |
| Flight | 航班基础信息与余票数据 | flightNo, departureCity, arrivalCity, departTime, arriveTime, price, remainingSeats | findFlight(condition), updateSeats() |
| Ticket | 预订机票的订单记录 | ticketId, userId, flightId, status, createTime | book(), refund(), modifyPassengerInfo(), print() |
| PersonalInfo | 用户的扩展个人信息 | userId, realName, idCard, phone | query(), update() |
类之间的关联关系值得单独说明。User 与 Ticket 是 1 对多的组合关系:一个用户可以有多张机票订单,订单生命周期从预订到退票都由用户触发。Flight 与 Ticket 是 1 对多关联:一个航班对应多张已售票据,且退票时余票数量要回滚。User 与 PersonalInfo 是 1 对 1 关联,两者可以分开存储,避免无关字段拖累登录表查询性能。
很多初稿画类图时只画了实体类,没有画控制类或边界类,导致后续画时序图时找不到对象来承接交互逻辑。比如"航班查询"这个用例,时序图里除了 Flight 实体对象,还需要有一个 FlightController 或 SearchService 之类的控制对象来接收查询条件、调用数据访问层、封装返回结果。这份文档的时序图部分在登录、注册、退票场景里都体现了这种控制类承接模式,照着这个思路去补其他用例的时序图就不会断链。
4.2 时序图与协作图:同一组交互的两种视图
这份文档提供了用户登录、用户注册、用户退票、添加航班信息、查询并修改个人信息、查询并修改航班信息等多张时序图,以及查询并修改个人信息、订票与查票两组协作图。时序图与协作图描述的是同一组交互过程,区别在于时序图强调消息的时间顺序,协作图强调对象之间的链接关系。课程设计里多数人只画时序图,协作图可有可无,但原文保留了这两张协作图,说明作者在动态建模上是有意识地做了多视角覆盖。
以用户登录为例,从时序图可以提炼出标准交互步骤,如表 4 所示。
| 序号 | 参与者动作 | 系统响应 | 涉及对象 |
|---|---|---|---|
| 1 | 用户输入用户名密码并点击登录 | 接收登录请求 | LoginController |
| 2 | 无 | 校验用户名密码 | User 实体,数据库 |
| 3 | 无 | 校验通过,创建会话 | Session 对象 |
| 4 | 无 | 跳转登录成功页面 | 视图层 |
| 5 | 密码错误或用户不存在 | 返回错误提示 | 视图层 |
登录时序图里有一个细节值得注意:原文的异常事件流区分了"未输入密码"和"未输入用户名"两种场景,而这两种校验在时序图上应该表现为发送消息之前的前置判断,而不是进入 User 校验之后的分支。如果把这层逻辑画错了,评审会认为你对"前端校验"和"后端校验"的边界没有概念。
4.3 状态图:把机票生命周期从"已预订"到"已退票"串起来
摘要里总结了状态图的四组关键状态:用户登录状态(未登录、登录成功、登录失败)、航班查询状态(未查询、查询成功、查询失败)、机票预订状态(未预订、预订成功、预订失败)、退票状态(未退票、退票成功、退票失败)。
实际建模时,最有价值的状态图是机票对象的状态流转图。一张机票至少经历四个状态:待支付、已支付、已使用或已退票。再加一个限制条件——航班未发出时才允许退票,就把状态图与需求里的退票约束直接挂钩了。课程设计里如果能把机票状态图单独立出来画,并且标注状态转换的触发事件(用户点击付款、用户点击退票、航班起飞),这几乎是答辩时的加分项。
状态图的画法有一个常见错误是混淆用户状态和业务对象状态。比如"用户登录失败"是用户的会话状态,不是机票的状态;如果把用户状态和订单状态画在同一张状态图里,主线会乱。正确做法是每张状态图只描述一个对象的生命周期,登录状态画一个用户会话状态图,机票状态单独画一个订单状态图。
5. 避坑与常见问题:从文档到答辩的四个典型翻车点
5.1 拿到文档后建议先做的三步核对
核对清单第一条是用例 ID 一致性。原文用例 ID 从 1 排到 16,时序图引用时应该与规约编号对应。实际检查时发现"订票管理"和"航班信息管理"两个用例 ID 是 15、16,却分别出现在用户和管理员的用例场景中,引用时若写错编号,答辩时被追问会非常被动。
第二条是角色复用检查。普通用户和管理员都涉及登录、查看个人信息、修改个人信息这三个用例,如果按角色各画一张用例图,这三个用例会被重复画两遍。正确做法是在角色用例图里对复用用例画扩展关系,或单独抽一个公共用例集合。
第三条是异常流补全。原文 14 份用例规约中,机票预订的异常事件流为空,航班删除和统计订票数据的异常事件流也过于简略。这会导致测试用例设计缺少负向场景,建议按"数据不存在、参数不合法、状态不满足前置条件"三个维度逐条补。
5.2 四个高频翻车点
翻车点一:游客画成独立参与者导致用例归属混乱。
现象:用例图里画了一个"游客"参与者,给它分配了注册、登录两个用例,但需求明明写的是"游客只能访问首页"。答辩时被问"游客能不能进入订票流程",回答前后矛盾。
原因:把访问者级别和业务参与者混为一谈。未注册用户只是系统未认证的访问状态,不是业务角色。
解决:把注册、登录放在面向所有访问者的认证用例集合里,游客不作为业务参与者,业务用例只分注册用户和管理员两组。
翻车点二:用例规约里缺少异常事件流,测试用例无从设计。
现象:规约里只写了"用户输入查询条件→系统响应→显示结果",完全没有异常分支。评审问"查询条件为空怎么办",只能临场编。
原因:写规约时按"最顺利的路径"写了一遍,没有按"每一步都反过来想一遍"的方式检查。
解决:每个用例规约至少补两条异常事件流——必填项为空时的提示、目标数据不存在时的提示。航班查询补"未输入查询条件",退票补"航班已发出无法退票",注册补"用户名已存在"。
翻车点三:类图画了五个实体类,但画时序图时找不到控制类对象。
现象:类图里只有 User、Flight、Ticket 等实体类,时序图里却要画"用户点击登录按钮后对象之间怎么交互",发现没有对象承接这个动作。
原因:只在类图里画数据实体,忽略了边界类(页面类)和控制类(控制器/服务类)。
解决:补一个 Service 或 Controller 层类,例如 LoginController、FlightService、TicketService。时序图的每个消息箭头两端至少有实体类或控制类的对象,否则消息发不出去。
翻车点四:状态图把用户状态和订单状态混在一张图里。
现象:一张状态图上既有未登录、登录成功,又有已预订、已退票,状态节点超过十二个,连线乱得没法讲。
原因:没有区分监测对象的生命周期。
解决:一个状态图只画一种对象的生命周期。登录状态图只画用户会话状态,机票状态图只画票的状态与触发事件,退票约束作为状态转换的守卫条件标注在箭头上。
6. 最后一步:把 UML 设计转成交付材料的实操顺序
拿到这份文档后,不要急着从头到尾读一遍,按下面这个顺序处理效率会高很多。
第一步,核对原文档的目录结构与图表编号。原文档是 Word 格式,图注、表注、用例规约编号分散在各章,建议通读一遍后先补一个图表索引表,列清楚图名、图号、所在页码。答辩时评审最喜欢现场翻文档找某一张图,索引表能让这个过程顺畅很多。
第二步,把用例规约导出成可测试的验收清单。用"用例 ID + 基本事件流 + 异常事件流"三列做成表格,后续写代码时每实现一个用例就往里勾选。如果每个用例的异常事件流补全了,后端接口的参数校验规则就自动有了,测试用例也能直接从这里生成。
第三步,检查类图中的实体类是否覆盖了所有用例数据。打开类图,逐一核对"添加航班"用例中航班信息的属性、"打印票据"用例中票据需要输出的字段,如果类图里缺字段,及时补上并同步到数据库设计文档。这一步是文档与代码实现之间最脆弱的环节,缺一个字段后面就要整个表返工。
第四步,将 Word 版导出为 PDF 时锁定修订模式,保留所有审阅痕迹。实际项目里一份设计文档要经过需求评审、设计评审、答辩评审三个阶段,前后的修改记录能说明哪些需求是后来追加的,哪些设计是答辩前临时调整的。有个小习惯值得分享:每次做 UML 建模,我都先把 Word 文档另存一份带修订记录的副本,哪怕只是微调用例名称,也留着修改历史。评审问"为什么这个用例从 3 版开始才出现",打开修订记录就能还原改动过程,不用凭记忆解释。反之,直接在原文件上静默修改,到了答辩现场被追问版本差异,就成了黑匣子,谁也说不清。
从那以后,我每次拿到任何一份 UML 设计文档,无论来源是哪里,都强制先把这三样核对掉:用例规约的异常流是否补全、类图是否与控制类对应、各图之间的编号是否一致。这套检查前后用不了二十分钟,但能避免答辩场上八成以上的尴尬提问。希望帮到你。
本文还有配套的精品资源,点击获取