作业集1~3的总结性Blog
一、前言
这三次作业集围绕航空器配载与货运管理这一主题展开,通过三次迭代开发,来逐步完善这个系统的功能。
第一次作业集:中等难度,核心是基础航班货运配载的面向对象设计,遵循单一职责原则,完成航班、货物、装载清单等类拆分,实现货物按重量降序装载、总重计算与超载判断,涉及封装、集合、冒泡排序和输入输出处理。
第二次作业集:中等偏难,在基础配载上迭代多货舱管理,需实现货舱、航班、调度等类,处理组合 / 聚合关系,完成货物绑定目标货舱、舱位与航班双重超载校验、多状态输出,强化输入校验与复杂业务逻辑组织。
第三次作业集:较难,聚焦航空器载重平衡计算,新增旅客、行李细粒度类,结合空机、旅客、货舱数据做力矩、重心、重心百分比换算,判断配平安全状态,需严格校验各类非法输入、容量预警并生成格式化载重平衡舱单。
二、设计与分析
(1)NCHU_航空器配载与货运管理系统1
1.类图:

本次作业共设计了6个核心类,严格遵循单一职责原则:
Flight类:仅负责管理航班信息和重量计算,提供addCargoWeight()、isOverload()等方法
Cargo类:仅负责存储货物名称和重量,是纯粹的数据载体
LoadManifest类:负责维护货物清单,体现聚合关系
CargoSorter类:独立负责排序算法,使用冒泡排序实现重量降序排列
CargoLoadService类:配载业务类,协调排序和重量累加
CargoPrintUtil类:纯输出工具类,负责格式化打印
2.SourceMontor的生成报表内容:

从SourceMonitor报表可以看出,第一次作业的代码结构较为简单:
| 指标 | 数值 | 分析 |
|---|---|---|
| 总行数 | 127行 | 代码量适中,符合入门作业规模 |
| 语句数 | 62条 | 核心逻辑清晰,无冗余代码 |
| 分支语句占比 | 8.1% | 主要来自循环和条件判断 |
| 最大嵌套深度 | 4层 | 出现在排序算法的双层循环中 |
| 平均块深度 | 0.76 | 整体结构扁平,可读性良好 |
心得: 本次作业让我初步理解了单一职责原则的含义,将Flight、Cargo、LoadManifest等类职责分离,我体会到了“一个类只做一件事”带来的代码可读性提升。
(2)NCHU_航空器配载与货运管理系统2
1.类图:

本次作业新增和优化的类包括:
Position类:表示货舱中的一个位置(行、列),提供getPosName()方法
CargoCompartment类:货舱类,与Position是组合关系(货舱创建时内部生成Position列表),与Cargo是聚合关系
CargoWithTarget类:绑定货物与其目标货舱ID
LoadDispatcher类:调度类,负责货物按重量降序排序和查找货物
InputValidator类:输入校验类,提供整数、浮点数的范围校验方法
InputReader类:负责统一读取输入,封装Scanner操作
组合关系:Position对象的生命周期由CargoCompartment完全管理,符合组合关系的定义。
聚合关系:Cargo对象在装载前就已存在,即使从货舱中移除,Cargo对象依然存在,符合聚合关系的定义。
2.SourceMontor的生成报表内容:

根据SourceMonitor生成的报表,代码规模如下:
| 指标 | 数值 | 说明 |
|---|---|---|
| 文件行数 | 324行 | 较第一次作业有显著增长 |
| 语句数 | 168条 | 核心逻辑密度适中 |
| 分支语句占比 | 11.3% | 主要来自条件判断和循环控制 |
| 方法调用语句 | 56条 | 体现类间协作的频繁程度 |
| 类/接口数量 | 4个 | 类数量较少,但实际好像并非如此 |
| 每类方法数 | 10.00 | 平均每个类有10个方法,职责不够集中 |
| 每方法平均语句数 | 4.03 | 方法体较为简短 |
| 最大复杂度 | 4 | 最复杂方法的圈复杂度为4 |
| 最大嵌套深度 | 5层 | 出现在核心业务逻辑中 |
| 平均嵌套深度 | 1.29 | 整体结构较为扁平 |
| 平均复杂度 | 1.69 | 多数方法复杂度较低,易于维护 |
(3)NCHU_航空器配载与货运管理系统3
1.类图:

本次作业在上一次作业的基础上,主要进行了以下变更:
新增类:
Passenger类:仅负责管理旅客行李及计算旅客总重量(含标准体重75kg),与Luggage是组合关系
Luggage类:仅负责记录行李重量,作为Passenger的组成部分
WeightBalanceCalculator类:纯计算工具类,仅负责根据航空力学公式计算总重量、总力矩、重心及百分比
修改类:
Flight类:新增List<Passenger>属性,新增getTotalPassengerWeight()等方法
CargoCompartment类:新增getArm()方法(根据货舱ID返回力臂)、getTotalWeight()方法
InputValidator类:从纯范围校验扩展为统一的输入读取+校验静态方法
Main类:输入逻辑完全重构,增加旅客行李输入、前后舱货物分别输入
删除/简化类:
CargoWithTarget类:因输入格式变化(货物按舱分类输入而非指定目标舱)而不再需要
CargoLoadExecutor类:装载逻辑简化为直接遍历前后舱货物列表
2.SourceMontor的生成报表内容:

对报表内容的分析如下:
| 指标 | 数值 | 说明 |
|---|---|---|
| 文件行数 | 225行 | 较第二次作业反而减少,有我特意压缩行数的原因 |
| 语句数 | 120条 | 核心逻辑密度适中 |
| 分支语句占比 | 12.5% | 三次作业中最高,主要来自配平计算的条件判断和输入校验 |
| 方法调用语句 | 37条 | 类间协作频繁度降低,得益于InputValidator的内聚设计 |
| 类/接口数量 | 8个 | 类数量适中,符合题目要求 |
| 每类方法数 | 3.50 | 平均每个类有3-4个方法,职责集中 |
| 每方法平均语句数 | 2.43 | 三次作业中最短,方法体高度精简 |
| 最大复杂度 | 4 | 最复杂方法为LoadDispatcher.sortByWeightDesc() |
| 最大嵌套深度 | 5层 | 出现在货物装载的循环判断中 |
| 平均嵌套深度 | 1.78 | 整体结构较为扁平 |
| 平均复杂度 | 1.37 | 三次作业中最低,代码简洁高效 |
三、踩坑心得
(2)航空器配载与货运管理系统2:题目要求CargoCompartment与Position是组合关系,意味着Position对象必须在CargoCompartment构造器内部创建,而不是从外部传入。我最初理解不够深入,试图在外部创建Position列表再传给货舱,这违反了组合关系的定义。后来我仔细阅读题目要求,发现必须在构造器内部用循环生成Position对象,这才纠正了设计;题目要求先按重量降序排序,再依次尝试将货物装入指定货舱。我的代码实现了排序,但在装载时没有体现“逐件尝试”的过程。从测试结果看,部分测试点失败,我不知道失败的测试点是测试什么的,但我怀疑可能是因为我在装载失败时的处理逻辑有误,只是目前还没有解决;我还是要提一下注意输出格式的问题,建议直接从题目里复制过来,确保格式没错,当然,类似总重量值之类的不能直接复制,建议结合输出样例去理解。
(2)第二次作业中,我的InputValidator类只提供了范围校验的静态方法,但没有主动读取输入。改进建议是将输入读取和校验合并在一个方法中,例如定义一个readIntWithRange方法,在读取整数的同时进行范围校验,这样可以减少Main类中的重复代码。
浙公网安备 33010602011771号