航空订票系统UML建模:用例图、时序图与类图实战指南 简介航空订票系统是典型的信息管理系统设计案例适合软件工程、系统分析与设计课程的学生以及正在学习UML建模的开发者参考。资源以UML可视化建模为主线覆盖用例图、类图、包图、顺序图、协作图、状态图、活动图、组件图与部署图完整展示了新用户注册、登录验证、航班查询、机票预订与退票等核心业务的建模过程。作者结合Rose工具绘制图表并针对用户权限、信用评价交互、类间继承与依赖关系等关键点做了梳理能帮助读者理解如何将抽象业务需求转化为规范的系统模型。资源共1个文件为PDF格式整体大小约2.04MB便于直接阅读与存档。目前已有1958人浏览学习适合作为课程设计参考或UML实战入门资料。1. 航空订票系统的UML建模设计为什么画图比写代码更先决一份航空订票系统的UML建模设计文档摆到面前新手的第一反应通常是翻类图画得是否工整我的第一反应是先看用例图和时序图。原因很简单用例图定义系统边界时序图定义对象协作这两张图如果一开始就歪掉后面类图、状态图画得再规范落到代码时也会处处打架。这套笔记把建模过程拆成一条可照做的路线先厘清角色与用例再做静态结构建模再做动态行为建模最后给出避坑清单并反推数据库表与接口。适合正在做课程设计、准备软考中级或者第一次独立承担需求建模的开发者。2. 用例建模把订票业务拆成角色、用例与边界用例是整个建模的地基。很多文档把用例图画成一张到处是箭头的功能清单评审会上被问到“支付网关算哪边的角色”“取消订单和退款是几个用例”就答不上来。这里的做法是先定角色再拆用例最后补用例描述每一步都对应可以交给别人评审的产出物。2.1 角色识别乘客、管理员与航空公司不要漏掉外部系统动手画图之前先从业务描述里找主语。航空订票系统最典型的主语是普通乘客、系统管理员、航空公司票务和支付网关。其中支付网关是最容易被漏掉的一个——它不在你系统内部但它参与了支付过程必须作为外部参与者出现在用例图里否则后续时序图里支付回调这段就找不到归属。角色定位与系统的关系Passenger乘客核心用户注册后可购票查询航班、预订订单、支付、取消、值机Visitor匿名访客未登录用户只能查询航班订票前要引导登录Admin系统管理员运营方维护航班、管理价格、处理售后订单AirlineAgent航司票务外部柜员处理线下值机和航班变动通知PaymentGateway支付网关外部系统接收支付请求回调支付结果判断一个角色到底放在系统边界内还是边界外就看一条这个角色是否由你所在的系统负责实现。支付网关不是你开发的它只是被调用那就画在边界外乘客登录状态如果由第三方认证服务提供那认证服务也要画在边界外而不是做成一个用例下的按钮。2.2 用例图怎么画从订票主流程拆出核心用例用例不是操作步骤而是参与者能完成的有业务价值的目标。订票系统里“点击查询按钮”不是用例“查询航班”才是“输入乘机人信息”不是用例“预订机票”才是。拆法可以按四步走列出业务动词查询、预订、支付、取消、值机、退改签、航班管理、订单管理。过滤掉系统内部动作把“校验登录”“生成订单号”“发送短信”这类实现细节先放到用例描述里不单独画成用例。确认每个用例都有明确的参与者且参与者能观察到结果。画一个系统边界矩形用例放里面角色放外面。用例名参与者前置条件后置条件查询航班乘客 / 匿名访客无返回可售航班列表预订机票乘客已登录存在可售航班生成待支付订单锁定舱位支付订单乘客有待支付订单订单状态变为已支付取消订单乘客订单已支付且未出票释放舱位生成退款单办理值机乘客订单已出票生成电子登机牌管理航班管理员已登录后台航班时刻表更新处理退改签管理员乘客提交申请原订单状态变更新订单生成这里要注意“取消订单”和“退票”是不是一个用例。我的习惯是按触发结果拆用户主动在前台取消未出票订单和用户提交退票申请由后台审核两者动作和规则不同拆成两个用例后续状态图也更好画。2.3 用例描述的写法主事件流、备选流与前置条件的落地模板用例图只画椭圆和连线是交不了差的真正有价值的是每个用例的文字描述。软考中级案例题里经常直接给一段业务描述让你补全用例描述答题套路就是下面这个模板字段内容用例名称预订机票参与者乘客前置条件乘客已登录存在可售的航班舱位主事件流1. 乘客提交出发地、目的地和日期2. 系统返回可售航班列表3. 乘客选择航班与舱位等级4. 系统校验登录状态5. 系统创建待支付订单6. 系统返回订单号与支付金额备选流3a所选舱位已被占用系统提示重新选择4a登录已过期系统引导重新登录后回到步骤35a库存扣减失败系统回滚并提示稍后重试后置条件生成一条待支付订单对应舱位被锁定主事件流里的每一步后面画时序图时几乎能一对一地变成消息。这也是为什么我在评审时优先看用例描述而不是看图的原因——描述写得含糊图一定画不扎实。备选流是很多人偷懒的地方但支付超时、库存不足、登录失效这些分支恰恰是系统最容易被用户骂醒的场景。3. 静态结构建模类图与对象图的绘制规范和箭头含义用例解决了“哪些人能做什么”接下来要回答“系统里有哪些实体、实体之间怎么互相持有”。这一章的核心是类图。类图也是软考中级里最常考的一类图尤其是画箭头和判断关系基本是必考点。3.1 实体类识别从用例名词里抽类而不是从数据库反推有人习惯先把数据库表设计好再照着表反向画类图这个习惯我不推荐。建模设计文档的价值在早期先定义好对象再谈存储顺序反了会漏掉业务对象。正确做法是从用例描述里做名词过滤把候选实体捞出来。候选类关键属性来源用例UseruserId, userName, mobile, passwordHash注册、登录、预订机票FlightflightNo, departure, arrival, takeoffTime, landingTime, cabinCapacity查询航班、管理航班OrderorderId, userId, status, totalAmount, createdAt预订机票、支付订单、取消订单OrderItemorderItemId, orderId, flightId, cabinClass, passengerName预订机票、办理值机PaymentpaymentId, orderId, amount, channel, callbackTime支付订单类图命名有个约定类名用名词单数属性用小驼峰类型放在冒号后。类名和属性名一旦确定后面生成数据库表、写后端实体类都用同一套词减少翻译损耗。另外DTO 和 Entity 从一开始就分开建模不然订单类和订单视图对象混在一起类图会变成一锅粥。3.2 UML类图箭头含义依赖、关联、聚合、组合、泛化的区分类图翻车的重灾区就在箭头上。UML 里关系一共五类每一类的画法和语义都不一样评审时被考官盯着箭头问是常有的事。关系画法语义订票系统里的例子泛化实线空心三角箭头指向父类is-a继承Passenger 继承 User实现虚线空心三角箭头指向接口implements实现接口PaymentService 实现 PaymentGatewayClient依赖虚线普通箭头指向被使用者方法参数、返回值、局部变量里用到对方OrderService 依赖 PaymentClient关联实线普通箭头长期持有的引用has-aUser 关联 Order一个用户有多张订单聚合实线空心菱形在整体侧弱拥有整体销毁个体仍存在Order 聚合 Payment订单删除后支付流水保留组合实线实心菱形在整体侧强拥有整体销毁个体一起销毁Order 组合 OrderItem订单删除明细一起删最容易混的是聚合和组合判断标准就一条整体没了部分还在不在。支付流水要在订单删除后继续保留用于对账所以是聚合订单明细跟着订单走订单没了明细没有存在意义所以是组合。菱形永远画在整体那一侧箭头指向的是被拥有的那一侧方向画反是高频扣分点。3.3 类图里的属性与方法MVC分层状态如何影响建模类图不是把所有实体堆在一张图里就完事。后端按 Controller、Service、Repository 分层时各层有自己的类视角全塞进一张图会导致依赖关系乱成一团。我一般把类图拆成两张一张实体关系图只画 Entity 和它们之间的关系一张核心协作图只画 Service 之间的依赖。类图里的方法不需要把所有 getter/setter 都画出来只画有业务含义的行为。比如 Order 类里要有一个 pay()OrderItem 不需要有任何业务方法它只是数据的载体。对于 Service 类方法签名要写完整因为后面时序图的消息名会和它对上。分层建模时遵循三条规则Controller 只依赖 Service 接口Service 依赖 Repository 和领域实体Entity 不反向依赖 Service。提示这是评审时最容易被问“为什么类图里没有 orderStatus 属性”的地方。状态字段务必在实体类里画出来否则后面状态图就是无源之水。4. 动态行为建模时序图、状态图与活动图的分工类图描述的是“静态结构”但系统真正跑起来是对象之间不断发消息、状态不断变化的过程。动态行为建模就是把这部分讲清楚。UML 里动态结构图包括时序图、通信图、状态图和活动图这一章把订票系统最常用的三张讲透。4.1 时序图订票主流程的寿命线与消息顺序时序图画的是“谁在什么时候调用了谁的哪个方法”。订票主流程的消息顺序如下乘客向系统发起查询航班消息参数是出发地、目的地和日期。系统向数据库或航班服务查询可售航班列表。乘客选择航班和舱位系统返回可售舱位与价格。乘客提交乘机人信息系统创建待支付订单。系统向支付网关发起创建支付请求。支付网关回调支付结果系统更新订单状态为已支付。系统异步触发出票成功后通知乘客出票信息。消息命名统一用动宾结构比如 createOrder(orderInfo)、queryFlight(queryParam)、paymentCallback(paymentResult)。这一步直接决定了后续接口文档能不能写清楚。时序图不需要每个请求都画一条返回虚线只画关键的返回消息就好否则图上一大堆回箭头时间线根本没法读。返回消息注意要和请求消息使用相同命名只是方向相反。4.2 状态图订单状态流转是建模设计的重点订单是订票系统里生命周期最长的对象从创建到完成要经过多个稳定的中间状态这正好是状态图的用武之地。状态图建模不画动作步骤画的是“在某个状态下发生了某个事件跳到另一个状态”。当前状态触发事件下一状态初始乘客提交订单待支付待支付支付成功回调已支付待支付用户取消 / 支付超时自动关闭已取消已支付出票成功已出票已出票乘客办理值机已值机已值机航班起飞并落地已完成已支付乘客提交退票申请退票中退票中审核通过并退款已退款一个常见的建模错误是把“待支付”直接指向“已出票”跳过了“已支付”状态。出票的前提是支付完成中间状态不能省。另一个错误是只画主路径不画超时关闭、退款审核这类备选状态导致测试用例设计时漏掉边界场景。状态图的价值其实在于逼你列出所有分支。4.3 活动图用泳道表达支付超时与异步出票活动图适合表达业务流程中的并发和职责划分。订票支付就是一个典型场景乘客提交支付后系统同时启动“等待支付结果”和“支付超时计时”两个分支先到先触发。活动图里“泳道”按角色划分每个人在任何泳道内的活动表示该角色负责的动作。订票支付活动图可以分三条泳道乘客、系统、支付网关。乘客泳道里只有“提交支付确认”系统泳道里有“创建支付请求”“开启超时计时”“接收支付回调”“更新订单状态”支付网关泳道里有“处理扣款”“返回结果”。并发分支用一条粗横线分叉和汇合分叉后两条支线并行直到都到达汇合点才能继续。活动图和流程图的区别就在这里流程图只能一条线走到底活动图可以表达并行分叉、汇合和职责分区。业务规则中有“同时做两件事”或“谁先完成谁决定走向”的描述时优先考虑活动图。4.4 UML中的动态结构图包括哪些选图依据如果你在准备软考中级选择题里会直接考“UML 动态结构图包括哪几种”。答案是时序图、通信图、状态图、活动图。其中通信图也叫协作图与时序图同属交互图只是表达重点不同。表达目标选用图图的核心特点消息发生的时间顺序是否严格时序图有生命线和时间轴强调先后对象之间消息往来的结构关系通信图无时间轴强调对象间的连接对象生命周期内的状态变化状态图有状态和事件无状态跳转就是错的业务规则里的并发与职责分配活动图有泳道、分叉、汇合选图可以按一句话记忆要交代前后次序选时序图要交代关联结构选通信图要交代状态变化选状态图要交代流程并发选活动图。盯住你的问题是什么别贪多把四张图全画一遍。5. UML建模避坑指南五类高频错误的成因与修正画图看着自由实际上每张图都有自己的边界和语法约束。下面这五个坑是我在评审建模设计时最常碰到的按“现象 → 原因 → 解决”的顺序说清楚照着自查能省不少事。5.1 用例图画成操作菜单这是最容易翻车的一类现象用例图里全是“点击查询”“输入乘机人”“点击支付按钮”这种椭圆角色和用例之间连着一堆箭头看起来像操作流程图。原因把“用户的动作”当成了“用户的业务目标”。点击按钮是实现细节不是一个可以从外部观察结果的完整过程。解决写用例名时强迫自己回答“完成这件事用户得到了什么”。得到航班列表叫“查询航班”得到一张可退改的订单叫“预订机票”得到支付成功确认叫“支付订单”。实现细节全部下沉到用例描述的主事件流里去。5.2 类图关系乱用箭头方向与基数标错现象所有有关联的类一律画实线普通箭头或者全部画成依赖虚线聚合和组合的菱形画在部分那一侧一对多关系不标基数。原因对五种关系的语义没有形成判断链画图时凭感觉审图时也没有检查规则。解决按先生命周期、后引用强度来判断。整体销毁后部分仍在选聚合整体销毁部分一起销毁选组合只是方法里短暂用到选依赖长期持有引用选关联。菱形画在整体类那一侧基数必须成对出现比如订单这一个整体侧标 1明细那侧标 1..*。5.3 时序图消息命名不规范消息不是数据流现象时序图里的消息名称是“订单信息”“支付结果”“航班数据”这类名词短语或者干脆用中文描述“把订单传给支付系统”。原因把时序图画成了数据流图消息名直接沿用了业务名词没有对应到真实的方法调用。代码落地的时候这种消息名没法映射到接口最后只能靠人肉理解。解决一律改成“动词 宾语 参数”的结构。查询航班信息就写 queryFlights(queryParam)创建订单就写 createOrder(orderInfo)支付回调就写 paymentCallback(result)。消息名和类图里的方法名保持同名词时序图才能真正指导编码。提示评审时用手指着时序图上每个消息问一句“这个背后的方法在哪个类里”答不上来就要回头改。5.4 状态图与活动图混搭状态没有事件驱动现象状态图里画了菱形判断分支活动图里出现“等待支付状态”“审核中状态”这种文字。原因把状态和活动混为一谈。状态是对象对外表现出的稳定可观测条件必须由事件触发迁移活动是系统执行的动宾短语分支可以自动产生不需要事件触发。解决画状态图时先列出所有事件名词比如“支付成功”“用户取消”“出票完成”再去搭图。没有事件参与的过程就不要在状态图里出现。画活动图时把“状态”这个词换成“动作”比如“等待支付结果”是一个动作分支不是状态。5.5 图与图之间对不上建模没有回查迭代现象用例主事件流写了 5 步时序图画了 7 个消息类图 Order 没有 orderStatus 属性状态图里却有 5 个状态活动图的支付分支和时序图的消息顺序完全脱节。原因每张图独立完成完成后没有回查其他图。模型不是单张图的自洽而是整套图同一个世界观的延续。解决三个回查点必须走一遍。第一用例主事件流的每一步能在时序图里找到对应消息第二时序图的每个消息能在类图里找到对应的类和方法第三状态图里的状态值在类图里有对应字段在时序图里有对应更新时机。我一般画完一张新图就回头扫一遍旧图宁可多改两版也不要交付时被评审连环追问。6. 从模型到落地用UML图反推数据库表与后端接口建模的价值要落在代码里才算闭环。这里给出两条最常见的落地路径由类图反推数据库表结构由时序图反推后端接口列表。最后再提一个我常用的工具习惯。6.1 由类图映射数据库表一对多与多对多的处理类图上的关联关系可以直接翻译成建表规则。一对多关系在“多”方表里加一列外键比如 OrderItem 表要带上 order_id 和 flight_id 两个外键多对多关系必须建中间表比如乘客和常旅客计划的关联就是一个独立关系表。组合关系意味着级联删除订单表删掉时关联的明细表数据要清掉。6.2 由时序图推导接口消息顺序即接口清单时序图的消息顺序就是接口调用的顺序翻译时只需要把每个消息对应到 URL 上。时序图消息后端接口queryFlights(queryParam)GET /api/flights?departurePEKarrivalSHAdate...createOrder(orderInfo)POST /api/orderspaymentCallback(result)POST /api/payments/callbackcancelOrder(orderId)DELETE /api/orders/{orderId}6.3 用PlantUML把模型文本化便于评审与版本管理我现在的习惯是核心模型用 PlantUML 写每次评审改的是文本 diff而不是一张导出的 PNG 图。下面是一个简化版订单类图的写法startuml class Order { - id: Long - status: Integer - totalAmount: BigDecimal pay() : boolean cancel() : boolean } class OrderItem { - flightId: Long - passengerName: String - cabinClass: String } Order 1 o-- 1..* OrderItem : contains enduml这段文本渲染出来的效果和手画类图完全一致但它可以进 Git改一行就知道改了什么。时间序列图、状态图也可以用同样方式文本化比在画图工具里拖拽效率高很多也和建模设计文档的版本管理天然兼容。我现在的习惯是接到需求先把用例图和时序图理透再谈类图和建表。这两张图不顺类图画得再规范也是对空气建模。UML 的价值不在图本身在于它逼你把业务边界、协作顺序、状态迁移和数据结构一次性想清楚。希望这套流程能帮你少掉几次坑也希望帮到你。本文还有配套的精品资源点击获取