航空器配载与货运管理系统三次作业总结
航空器配载与货运管理系统三次作业总结
1 前言
这三次面向对象编程作业,它们围绕同一个主题——航空器配载与货运管理系统——一点点迭代升级。每次都是“装载、重量、超载判断”,但需求其实一直在变:一开始只有一个货舱,后来变成了多个货舱,到最后干脆把旅客、行李、货物、货舱加上载重平衡计算全塞进来,凑成了一套挺完整的航空配载系统。
知识点这块儿,三次作业覆盖很全面:类与对象、封装、单一职责原则(SRP),集合框架里List和数组都用上了,排序算法也练了选择排序和冒泡排序。另外输入校验、异常退出、物理力矩、重心百分比计算这些也没落下。
难度上是逐级递增的。第一次主要就是基础建模,照着题意把最核心的类搭出来,能跑通就行。第二次加入了多货舱、List集合,还要做装货分配和航班整体状态判断,业务结构一下子复杂了不少。第三次就更狠了,旅客、行李、配平算法全上来了,系统规模大了很多,逻辑也更绕。总的来说,这三次作业像是从“搭个简单模型”慢慢过渡到“模拟真实业务”的过程。
2 设计与分析
下面结合本人三次作业的提交源码、SourceMonitor 报表以及 UML 类图,对系统设计进行分析。
2.1 第一次作业
2.1.1 SourceMonitor 代码质量度量分析

共包含6个 Java 类、6个源码文件,总代码行数 89 行,有效执行语句 50 行;平均每个类包含 1.67 个方法,单个方法平均有效代码 2.20 行,方法拆分精简,无冗余长方法。复杂度层面,项目最大圈复杂度为 5,平均圈复杂度 1.70;最大嵌套深度为 3,平均嵌套深度 1.32。

从方法维度度量可见:
项目中Cargo及LoadManifest的属性获取、构造等基础方法圈复杂度均为1,封装简洁规范;
核心业务方法中,货物排序交换方法swapCargo()复杂度最高为5,是项目主要逻辑实现;addCargo()、getCargoAt()分别实现货物添加、索引查询,复杂度为 2、3;整体最大嵌套深度为 3。
2.1.2 UML 类图分析

本次类图严格对应基础配载业务,类间关系清晰:
这次类图跟基础配载业务对应得挺紧,类之间的关系也清楚。聚合关系有两处:Flight聚合LoadManifest(一个航班对应一份配载清单),LoadManifest聚合Cargo(一份清单里可以装多件货物)。依赖关系就是Main依赖所有业务类,还有CargoSorter和Printer依赖LoadManifest来排序和输出。
心得:头一次完成这类综合性大作业,还是蛮慎重。经过提醒知道即便测试点全部通过,若不符合题目要求仍会得零分,所以提交前反复测了好多遍,对着要求一条条核。这次作业让我第一次真切体会到:面向对象编程并非简单将代码拆分到不同文件,而是要围绕职责边界做精准建模。例如排序并没有写在LoadManifest中,而是单独放进CargoSorter工具类,这样耦合度就低了,也更符合单一职责原则(SRP)。同时我也深刻意识到封装性对代码有多重要。
2.2 第二次作业
2.2.1 SourceMonitor 代码质量度量分析

共包含8个 Java 类、8个源码文件,总代码行数 320 行,有效执行语句 193 行;平均每个类包含 3.75 个方法,单个方法平均有效代码 4.17 行,说明方法粒度划分合理。
复杂度层面,项目最大圈复杂度为 4,平均圈复杂度 1.79;最大嵌套深度为 5,平均嵌套深度 1.86。与第一次作业相比,代码量明显增加。

从方法维度可见:
Cargo、Position等实体类的构造、属性获取方法圈复杂度均为1;
核心业务中,LoadDispatcher的货物排序、调度、查找方法,以及Printer打印输出、InputValidator输入校验方法复杂度集中在3~4,为项目主要逻辑实现;整体最大嵌套深度为 5,集中在调度、排序逻辑中。
2.2.2 UML 类图分析

第二次作业加入组合与聚合的设计点。组合关系:CargoCompartment组合Position(意思是货舱一创建,里面的位置网格就跟着生成)。聚合关系:Flight聚合CargoCompartment(一对多),CargoCompartment聚合Cargo。依赖关系:LoadDispatcher、Printer、InputValidator都依赖实体类来完成调度、输出和校验。
心得:多货舱业务加进来以后,系统一下子复杂了不少。本次作业要求CargoCompartment中使用List集合,但因为Cargo类需要实现addCargo方法,货物存储我还是用了数组,没好好体会List带来的便利。另外这次新增了货物装载分配逻辑,输出也更绕了。通过这次设计,我对UML里组合和聚合的区别有了直观的感觉,不再是死记硬背概念,而是能结合代码和类图来理解。还有,题目也逼着我开始重视输入校验,专门写了个InputValidator类来处理非法数据。
2.3 第三次作业
2.3.1 SourceMonitor 代码质量度量分析

第三次作业共包含10个 Java 类、10个源码文件,总代码行数 362 行,有效执行语句 211 行;平均每个类包含 3.10 个方法,单个方法平均有效代码 4.13 行,方法粒度划分合理。
复杂度层面,项目最大圈复杂度为 4,平均圈复杂度 1.57;最大嵌套深度为 5,平均嵌套深度 1.68。虽然业务内容比前两次更完整,但从指标上看,代码结构仍然保持在较稳定的范围内。

从方法维度可见:
Cargo、Passenger等实体类的构造、属性获取方法圈复杂度均为1,封装简洁规范;
主程序、货物排序、舱单生成、重心计算等核心业务方法复杂度集中为4,是项目主要逻辑实现;输入校验方法复杂度为 3,保障程序鲁棒性。
2.3.2 UML 类图分析

本次严格按照题目指定关系设计,核心关系如下:
这次我严格按照题目指定的关系来设计,核心关系如下:组合关系有两处——Passenger组合Luggage(旅客构造器里直接创建行李对象,行李不能脱离旅客独立存在),以及CargoCompartment组合Position。聚合关系:Flight聚合CargoCompartment,CargoCompartment聚合Cargo。依赖关系:WeightBalanceCalculator依赖Flight(把航班对象作为参数传进计算方法),LoadDispatcher和InputValidator依赖实体类。
心得:第三次作业的业务最完整,也最像真实的航空配载系统。这次对InputValidator的设计要求更高了,要让它跟主流程保持依赖关系,主函数不用自己引入Scanner包,职责更单一。这次我完全抛弃了数组,全部改用List,切身体会到List在存储、排序和批量操作上的便利。另外题目要求引入静态常量参数,也让我有了这种意识。我进一步认识到:复杂系统要想搞定,关键在于把复杂业务拆成多个职责清晰的小模块,从简单的类入手,再到复杂类,最后做主类,一个一个击破。
3 踩坑心得
这一块是我在提交源码过程中遇到的坑和经验,确实花了不少时间反复调。
-
第三次作业执行顺序错误
题目的核心流程为:先输入所有数据,再装载货物,然后输出舱单,最后再排序。但我最初写代码时,将输出放在了排序之后,导致多个测试点无法通过。
![image]()
![image]()
修正后按照:输入→装载→输出舱单→排序。
![image]()
-
输入校验时不知道如何终止程序
题目要求检测到非法数值(负数或超出范围)时立即停止程序。最初我只用了return,而return只是退出当前方法。查阅资料后使用System.exit(0);才实现真正的立即退出。 -
货舱超载提示输出错误
在第二次作业中,我错误地将超载货舱的“当前载重”输出为0.0kg,未更新的载重量变量。
![image]()
调试后修正逻辑,超载时应输出实际已装载重量,而非 0,符合真实配载业务逻辑。
![image]()
-
超载检查的时机与输出格式
在产生舱单之前要对货舱进行超载检测,若某一个货舱超载,则需要给出相应警告并且停止,不再输出舱单,而我在后面把超载检测提前后才可以通过该测试。这说明程序流程的调整必须严格符合题目要求,不能随意更改执行顺序,特别是像这种一旦失败就要退出的任务。 -
百分号的输出
需要输出重心百分比。因为在printf中%,是格式说明符开始,因此如果要输出一个字面百分号,就需要写成%%。我一开始只写了一个%,结果造成错误。后来改为:System.out.printf("重心百分比(%%MAC):%.1f%%", CGM);才能正确显示。这个坑虽然很小,但是让我明白格式化输出要认真校对。 -
货物数量下限理解偏差
前舱货物件数p要满足1 <= p <= m,所以将nextIntInRange(1, m)保持规范调用。
心得:因为只有一个普通的测试用例以及十个相对简单测试点进行展示,在此期间要不断调整优化才能满足题目要求正如老师所说要“摒弃‘看数据改代码’的投机取巧,养成‘深挖需求、严谨设计边界’的工程习惯”。
4 改进建议
-
简化
WeightBalanceCalculator的代码冗余
第三次作业里,WeightBalanceCalculator类有很多静态方法,而且好多方法都需要传入List<Passenger>和List<CargoCompartment>这两个参数,重复率挺高。以后可以考虑:把相关参数打包到一个上下文对象里;提取一些公共方法;把配平计算和舱单打印分开。这样能让程序更简洁,也为以后扩展打好基础。 -
完善
InputValidator的校验范围
InputValidator输入校验类目前只实现了整型和浮点型的非负校验,以及整型范围校验,缺少对浮点数的范围校验。校验不够全面。以后可以增加浮点数范围校验的方法,提高程序的鲁棒性。 -
引入常量类管理物理参数
第三次作业里,空机重量、力臂长度、MAC参数这些散落在WeightBalanceCalculator类里。通过这次作业我了解到,可以用public static final定义一组常量来集中管理这些物理参数,这样便于维护也更安全。
5 总结
经过这三次作业之后,我对于面向对象程序设计有更加全面的认识以及理解,在以下几点上受益匪浅。
- 封装及单一职责原则:学会把不同的责任划分到不同的类里;理解“一个类只负责一件事情”对于可维护性的好处。
- UML 类图与代码实现的关系:会用组合、聚合、依赖来建立类之间的关系,也明白了类图不只是画个图,更是写代码之前重要的设计参考。
- 需求分析及边界思考:光考虑主要逻辑是不够的,还得想清楚输入顺序、异常退出、边界条件和输出格式。有些题目看着简单,不认真分析就会在测试时踩坑。
- 工具的使用:掌握了用SourceMonitor和PowerDesigner来分析代码和类图。
以后的学习中,我还需要提高:需求拆解能力、方法粒度把控能力、复杂业务建模能力,还有代码复用和结构优化的能力。
6 课程建议
-
希望题目里的关键限制能标得明显一点
像第一次作业要用选择排序、第二次作业报错提示要去掉括号里的中文、第三次作业货物数量不能是零(要大于等于一)这些条件,最好在题目里说明一下,这样我们不容易跑偏。 -
PTA 能不能加一些专门练语法的题
现在作业基本都是综合业务类的,Java基础语法练得少,比如字符串处理、集合遍历、格式化输出这些。希望PTA能放一些小练习,几分钟就能做完那种,方便我们复习基础,保持写代码的手感,后面做大作业也能更顺手。 -
给一两个非公开的边界测试点做参考
现在题目里只给了一个常规例子,后面还有十个简单测试点,我们自己测的时候很难想到所有边界情况,让我们自己去琢磨怎么处理,这样也能养成考虑边界条件的好习惯。






浙公网安备 33010602011771号