OPP第一次作业集总结

前言
三次作业的题量和难度逐步增加,每次刚接触时,我都会觉得较为困难,但三次结束后往回看,发现前面的作业集变得简单了。第一次作业仅需实现单一货舱的货物排序与超载判断,类图结构简单。第二次作业涉及多货舱、位置网格、货物按目标货舱装载,需设计组合/聚合关系,调度类分离排序与查找逻辑。第三次引入物理计算(重心、力矩、MAC百分比),要求严格的设计约束(禁用继承/多态),手写冒泡排序替代内置排序,同时增加旅客管理和输入校验,对代码组织和业务理解要求较高。

第一次作业

目标

设计一个基础的航班货运配载模块。系统需要记录航班的基本信息(航班号、最大起飞重量、最大业载重量)。地勤人员可以按照货物重量从高到低向该航班添加货物(货物名称、重量)。系统需要实时计算当前已装载的总重量,并判断是否超载。

设计与分析

看到题目后,首先明确核心需求:记录航班信息、按重量降序添加货物、实时计算总重并判断超载。需要四个实体类:Flight(航班号、最大业载)、Cargo(名称、重量)、LoadManifest(管理货物列表并提供添加、总重计算、超载判断)、Main(输入输出控制)。排序算法选择手写选择排序,因为题目强调“从高到低添加”。
算法

选择排序。

实现方法

使用ArrayList存储所有货物,读取完成后调用选择排序算法对货物按重量降序排列,最后遍历输出并判断是否超载

代码规模

第一次作业代码规模如下表

Source File Total Lines Source Code Lines Source Code Lines [%] Comment Lines Comment Lines [%] Blank Lines Blank Lines [%]
Flight.java 12 11 91.7% 1 8.3% 0 0%
Cargo.java 12 11 91.7% 1 8.3% 0 0%
LoadManifest.java 30 27 90.0% 1 3.3% 2 6.7%
CargoSorter.java 20 19 95.0% 0 0% 1 5.0%
Main.java 34 30 88.2% 2 5.9% 2 5.9%
Total: 108 98 90.7% 5 4.6% 5 4.6%

类图

Flight航班类
2. Cargo货物类
3. LoadManifest装载清单类(管理货物列表、计算总重、判断超载)
4. CargoSorter货物排序类(选择排序,按重量降序)
5. Main主类(程序入口,输入输出)

plantuml-diagram

时序图

plantuml-diagram (1)

复杂度分析

第一次作业的复杂度分析如下表

类名 总方法数 圈复杂度(总和) 最大方法圈复杂度 平均方法圈复杂度 最大嵌套深度 代码行数(Source Line)
Flight 3 3 1 1.0 1 11
Cargo 3 3 1 1.0 1 11
LoadManifest 6 8 2 1.33 2 27
CargoSorter 1 4 4 4.0 3 19
Main 1 2 2 2.0 2 30
总计/平均 14 20 4 1.43 3 98

可以看出CargoSorter的sortCargo方法复杂度较高,因为它本质上是手写了选择排序,是对Java内置排序方法不熟悉所导致。

踩坑心得

最初我使用的是冒泡排序来处理货物,但是测试点就是无法通过。后来我仔细观察题目,发现要按照货物重量从高到低向该航班添加货物,而冒泡排序是先添加了所有货物,再进行排序。将冒泡排序改为选择排序后,测试点成功通过了。

改进建议

CargoSorter.sortCargo()直接修改了LoadManifest内部的cargos列表排序后货物顺序变为按重量降序。如果后续需要按原始录入顺序输出或追溯,顺序已被破坏且不可恢复。我认为可以在CargoSorter中加一个新方法,不改变原来列表,返回一个新的列表

第二次作业

目标

设计一个扩展的航班货运配载模块,实现以下功能:

  1. 航班信息管理:记录航班号、最大起飞重量、最大业载重量。
  2. 货舱管理:
    每个货舱有唯一标识(如“前舱”)、最大载重、行数、列数(组成位置网格)。
    货舱与其位置是组合关系(CargoCompartment 创建时内部生成 Position 列表)。
    货舱与装载的货物是聚合关系(Cargo 可独立存在)。
  3. 货物装载:
    输入所有待装载货物(名称、重量、目标货舱ID)。
    系统先按货物重量从高到低排序,再依次尝试将货物装入指定的货舱。
    如果目标货舱的当前重量 + 该货物重量 ≤ 该货舱最大载重,则装载成功,否则装载失败并给出提示。
  4. 输出要求:
    按排序后的顺序输出每件货物的装载结果(成功或失败)。
    输出每个货舱的已装载总重量及状态(是否超载)。
    输出航班整体总重量及与最大起飞重量、最大业载重量的对比,判断整体是否超载。

设计与分析
货舱有唯一标识、最大载重、行数列数(位置网格),且货舱与位置是组合关系(货舱创建时内部生成Position列表)。货物必须指定目标货舱ID,装载时先按重量降序排序,再依次尝试装入对应货舱,并校验货舱容量。因此新增Position、CargoCopartment、LoadDispatcher和InputValidator。其中LoadDispatcher负责排序、查找货物和装载逻辑,与Flight形成依赖关系。

算法

排序算法:TimSort
查找算法:线性查找(Linear Search)

实现方法

对货物按重量降序排序后,根据每个货物的目标货舱ID尝试装载,并实时校验各货舱及航班的重量限制,最后输出配载状态。

代码规模

第二次作业代码规模如下表

Source File Total Lines Source Code Lines Source Code Lines [%] Comment Lines Comment Lines [%] Blank Lines Blank Lines [%]
Main.java 73 67 91.8% 0 0% 6 8.2%
Position.java 14 11 78.6% 1 7.1% 2 14.3%
Cargo.java 22 19 86.4% 1 4.5% 2 9.1%
CargoCopartment.java 42 36 85.7% 2 4.8% 4 9.5%
Flight.java 59 51 86.4% 1 1.7% 7 11.9%
LoadDispatcher.java 29 26 89.7% 1 3.4% 2 6.9%
InputValidator.java 9 8 88.9% 1 11.1% 0 0%
Total: 248 218 87.9% 7 2.8% 23 9.3%

类图

  1. Main主类(程序入口,输入输出)
  2. Position货舱位置类(表示货舱中的行、列位置)
  3. Cargo货物类
  4. CargoCopartment货舱类(管理位置网格、货物列表、当前重量及装载)
  5. Flight航班类
  6. LoadDispatcher调度类(货物排序、查找货物、装载货物到指定货舱)
  7. InputValidator输入校验类(整数/浮点数的范围校验)

plantuml-diagram (2)

时序图

plantuml-diagram (3)

复杂度分析

第二次作业的复杂度分析如下表

类名 总方法数 圈复杂度(总和) 最大方法圈复杂度 平均方法圈复杂度 最大嵌套深度 源代码行数
Main 1 7 7 7.0 2 67
Position 2 2 1 1.0 1 11
Cargo 4 4 1 1.0 1 19
CargoCopartment 5 6 2 1.2 1 36
Flight 6 12 5 2.0 2 51
LoadDispatcher 3 7 3 2.3 2 26
InputValidator 2 2 1 1.0 1 8
总计/平均 23 40 7 1.74 2 218

Main类的main方法复杂度较高,因为它包含了多个循环和条件判断(3个循环 + 3个分支),本质上是在主类中直接编写了完整的业务逻辑

采坑心得

货物在装载时并未与对应的货舱匹配,全部装入一个货舱。重新检查代码发现,代码运行时,对应货舱ID不匹配时,并未切换货舱,导致货物全部填入前舱。

改进建议

Position 类仅提供 getPosName(),无占用标记,也就是只提供了行和列,代码却没用到行和列。并且只考虑了货物的重量,没有考虑货架容量和货物数量。

第三次作业

目标

在第二次作业(多货舱货物装载)基础上,新增旅客管理、载重平衡计算功能。系统需计算飞机总重量、总力矩、实际重心及MAC百分比,并判断重心是否在安全范围内;同时要求手写冒泡排序替代内置排序,增加输入校验,非法输入立即终止程序。最终输出旅客清单、货舱装载明细、重心计算结果及安全判定。

设计与分析
第三次作业在第二次基础上新增旅客管理和载重平衡计算,先提取出预设常量(空机重量/力臂、旅客力臂、前后货舱力臂、MAC参数、安全范围),并明确计算步骤:旅客总重及力矩、货舱总重及力矩、全机总重及总力矩、重心、MAC百分比,最后安全评估。设计上增加Passenger(与Luggage组合,行李在构造器内部new)、WeightBalanceCalculator(静态工具类,无Flight成员变量,所有计算通过参数传入Flight对象)。排序算法被强制要求手写冒泡排序,因此LoadDispatcher的sortCargos方法改为双重循环实现。输入校验类InputValidator需提供统一的整数/浮点数范围校验,非法输入立即退出。

算法

冒泡排序

实现方法

先按货舱ID(1前舱/2后舱)把货物分别装到对应货舱的指定位置,然后对每个货舱内的位置列表用手写冒泡排序按货物重量降序排列,再通过配平计算类遍历乘客和货舱,累加总重量和总力矩,算出重心百分比,最后输出配平评估结果。

代码规模

第三次作业代码规模如下表

Source File (Class) Total Lines Source Code Lines Source Code Lines [%] Comment Lines Comment Lines [%] Blank Lines Blank Lines [%]
Flight.java 28 26 92.9% 1 3.6% 1 3.6%
CargoCopartment.java 55 48 87.3% 0 0% 7 12.7%
Position.java 27 21 77.8% 1 3.7% 5 18.5%
Passenger.java 21 17 81.0% 1 4.8% 3 14.3%
Luggage.java 11 9 81.8% 0 0% 2 18.2%
Cargo.java 16 13 81.3% 0 0% 3 18.8%
WeightBanlanceCalculator.java 62 55 88.7% 0 0% 7 11.3%
LoadDispatcher.java 25 23 92.0% 1 4.0% 1 4.0%
InputValidator.java 33 29 87.9% 1 3.0% 3 9.1%
Main.java 92 76 82.6% 0 0% 16 17.4%
Total (所有类) 370 317 85.7% 5 1.4% 48 13.0%

类图

  1. Flight航班类
  2. CargoCopartment货舱类
  3. Position货架位置类
  4. Cargo货物类
  5. Passenger旅客类
  6. Luggage行李类
  7. WeightBanlanceCalculator配平计算器(静态工具类)
  8. LoadDispatcher调度类,提供冒泡排序方法
  9. InputValidator输入校验类(静态工具类)
  10. Main主类,程序入口

plantuml-diagram (4)

时序图

plantuml-diagram (5)

复杂度分析

第三次作业的复杂度分析如下表

类名 总方法数 圈复杂度(总和) 最大方法圈复杂度 平均方法圈复杂度 最大嵌套深度 源代码行数
Flight 7 7 1 1.0 1 26
CargoCopartment 6 12 5 2.0 2 48
Position 6 6 1 1.0 1 21
Cargo 2 2 1 1.0 1 13
Passenger 3 3 1 1.0 1 17
Luggage 2 2 1 1.0 1 9
WeightBanlanceCalculator 6 11 2 1.83 1 55
LoadDispatcher 2 7 5 3.5 3 23
InputValidator 4 9 3 2.25 1 29
Main 2 19 18 9.5 3 76
总计/平均 40 78 18 1.95 3 317

Main.main 方法包含多个循环、条件判断和输出,圈复杂度约18。
LoadDispatcher.sortPositionsByCargoWeight 包含双重循环和条件交换,圈复杂度约5。
CargoCopartment.addCargoToPosition 包含两个分支和循环,圈复杂度约5。
InputValidator.getIntInRange 和 getDoubleInRange 各有约3。

采坑心得
输入数据非法,容量不足,评估危险测试等测试点不通过,猜测可能是输出格式出了问题

改进建议
虽然在CargoCopartment中,有addPosition方法添加位置网格,addCargoToPosition方法根据传入的行、列查找对应位置。但是没有考虑货物数量和网格数量,会出现货物数量超过网格数量的情况。

综合性总结

收获

本次迭代作业,每次作业都在前一次的基础上增加新需求,使我对需求与代码的联系的理解大大加深了。最开始我习惯把所有业务逻辑全部塞在Main中,现在会把不同的逻辑放在不同的类中,做到职责清晰。三次作业都有不同的限制,让我更加灵活运用代码。随着InputValidator类的加入,让我逐步掌握会非法数据的处理,并且考虑可能会出现的各种情况。本次作业集会让我对类图的绘制更加熟练。

不足
对算法的运用不熟练,靠基础堆上去,越到后面代码的复杂度越来越高

posted @ 2026-05-17 20:10  取名取得晕头转向  阅读(14)  评论(0)    收藏  举报