面向对象程序设计题目集一到三总结

一、前言

这篇blog是围绕航空器配载与运货管理系统三次不同难度迭代作业的总结,三次作业从单货舱货物排序超载判断,迭代到多货舱货物分配与容量检查,最终演变为包含旅客行李、重心计算与安全评估的完整航班配载系统。我将结合自己的实际代码,从类图设计SourceMonitor指标核心关系三个维度,深入分析自己在封装、复用、异常处理等方面暴露的问题。

1.1作业集的知识点和难度

作业 知识点 难度
作业一 类与对象、ArrayList、冒泡排序、简单封装 简单
作业二 多类协作、集合嵌套、基本验证 较难
作业三 复杂业务计算、输入验证、力臂概念

二、设计与分析

 2.1 第一次作业

2.1.1 类图及核心关系

image

核心关系:

1、CargoList 与 Cargo 是聚合关系:一个货物列表包含多个货物对象。

2、CargoSorter 与 CargoList 是依赖关系:排序器需要访问货物列表的内部数据进行交换。

2.1.2 SourceMonitor的报表截图

image

2.1.3 我的反思

1、整个项目零注释。如果一个月后回看,我会完全忘记排序逻辑和字段含义,这是极坏的习惯。

2、CargoList 几乎没起到封装作用,直接暴露内部 ArrayList,导致我在 Main 中写了 cargoList.cargo.get(i) 这样的代码,后续想改成 private 时发现到处报错。

2.2 第二次作业

2.2.1 类图及核心关系

image

核心关系:

1、CargoList 与 Cargo 是聚合关系:一个货物列表包含多个货物对象。

2、CargoSorter 与 CargoList 是依赖关系:排序器需要访问货物列表的内部数据进行交换。

2.2.2 SourceMonitor的报表截图

image

2.2.3 我的反思:

1、Main 的圈复杂度达到6,因为我在一个方法里完成了输入、装载循环、输出、四种超载判断。嵌套循环和条件分支叠加导致可读性极差,应该把装载逻辑抽取成独立方法。

2、CargoCompartment 语句数38,其中一半用于构造 Position 矩阵,但这些对象从未参与业务逻辑,属于过度设计。

2.3 第三次作业

2.3.1 类图及核心关系

image

核心关系:

1、Flight 类持有两个 CargoCompartment 对象(前货舱 [1] 和后货舱 [2]),以及一个 Passenger 列表。同时定义了空机重量、各力臂、MAC参数等静态常量,供全局计算使用。

2、CargoCompartment 包含 Position 列表(用于表示货舱内的行列布局)和 Cargo 列表(已装入该货舱的货物)。getCurrentWeight() 动态计算当前货舱总重。

3、Passenger 与 Luggage 是组合关系:每位旅客必然携带一件行李,行李重量可变。

4、WeightBalanceCalculator 独立负责物理计算:总力矩、重心(CG)、MAC百分比,与 Flight 的数据结构解耦。

5、InputValidator 提供输入合法性校验(非负、范围、超重预检),在 Main 中被实际调用。

2.3.2 SourceMonitor的报表截图

image

2.3.3 我的反思

1、Main 圈复杂度飙升至12,是因为我在输入阶段对每个数值都调用了验证方法,且验证失败直接退出,产生了大量分支。应该把每个输入段抽取成独立方法,例如 readFrontCargoCompartment(),以降低复杂度。

2、零注释问题依然存在。WeightBalanceCalculator.calculateMAC 中的公式没有任何说明,我以后可能会忘记它的物理意义。

三、踩坑心得

1、滥用无参构造器:写了 Flight() {;} 和 Cargo() {;} 但从未调用,增加冗余。教训:只提供必要的构造器。

2、直接访问其他类的字段:cargoList.cargo.get(i) 一时爽,之后想私有化时改到崩溃。教训:所有集合字段必须私有,对外提供 get(int) 和 size()。

3、创建未使用的对象:为了满足“货舱有行列布局”的需求,创建了 Position 矩阵但从未用来分配货物。教训:功能没想清楚之前不要写代码。

4、装载失败的数据残留:容量不足时只打印“失败”,货物还在原列表中。教训:必须区分“待装列表”和“已装列表”,成功后再移动。

5、零注释:一句注释都没有。教训:关键逻辑必须写注释。

6、getCurrentWeight() 每次都遍历累加:在 CargoCompartment 中,每次调用 getCurrentWeight() 都会遍历整个 cargo 列表。虽然货物数量不多,但多次调用(比如在装载循环中每次添加前检查容量)会重复计算。教训:可以用一个currentWeight 字段缓存,添加或移除货物时同步更新。

四、改进建议

1、以后所有 ArrayList 之类的集合,一律用 private,然后提供 get(int index)、size()、add() 这几个方法。再也不在外面直接写 xxx.list.get(i) 了。

2、搞两个列表:一个是还没装的货物,一个是已经成功装进货舱的。装成功一个就从待装里移走,加到已装里。这样就不会出现数据残留。

3、在 CargoCompartment 里加一个 currentWeight 字段,每次 addCargo 的时候累加,removeCargo 的时候减去。这样 getCurrentWeight() 直接返回字段值,不用每次遍历列表。

4、只要不需要修改集合、不需要用到下标,就用 for (Cargo c : cargoList) 这种写法,代码更简洁,也更不容易写错下标。

5、每次写完,自己多试几个边界情况:货物总重刚好等于最大载重、货物重量为0、货舱行列是1x1、没有旅客、只有一个货物等等。不要只试题目给的例子,自己多想想极端情况。

五、总结

做完这三次作业后,我感觉自己真的非常非常厉害!从第一次作业连集合封装都搞不明白,到第三次作业能算重心、评安全、搞平衡,我明显认识到了自己的成长轨迹。最开始我只是单纯练习类的基础写法,后来慢慢接触真实业务逻辑(货舱、旅客、力臂、MAC),最后居然能把前后货舱、旅客行李、重心计算完整地整合成一个能跑的系统。通过这三次练习,我对Java面向对象的理解确实更扎实了。

5.1 收获与成长

1、知识层面:我不再只停留在语法表面,而是真正学会了用类和对象去模拟现实场景。比如把“货物”“货舱”“旅客”抽象成独立的类,把“重心计算”单独抽成一个计算器,这些都让我体会到了“分而治之”的乐趣。同时,我也掌握了 ArrayList 的基本用法,知道了什么时候该用集合、什么时候用数组,不会再盲目选错数据结构。

2、习惯层面:通过一次又一次地调试、改错、删掉未使用的 Position、调整排序逻辑,我慢慢养成了写规范代码的习惯。以前写完能跑就行,现在会多问自己一句:这个字段要不要私有?这个循环会不会越界?以后加第三个货舱要不要改很多地方?这种思维上的变化,对我以后学习来说尤为重要。

3、信心层面:说实话,第三次作业做到一半(算力矩那段)我差点想放弃,但咬牙做完后,看到 重心百分比: 31.5% 和 配平评估: 安全 (GREEN) 在屏幕上打印出来的时候,真的挺有成就感的。原来自己也能写出稍微像样一点的业务系统。

5.2 不足

1、虽然我顺利完成了三次作业,并且都拿到了满分,通过了所有测试点,但我也清楚自己还有很多短板。

2、首先,设计方面还很稚嫩。第二次作业里写了 Position 类却没用,第三次又把排序注释掉,说明我对“需求—设计—实现”的把控还不够稳。面对复杂一点的迭代,我依然习惯把逻辑堆在 main 方法里,没有做到真正的“高内聚、低耦合”。

3、其次,代码复用意识薄弱。第一次写了排序,第二次又写了一遍几乎一样的,第三次干脆把它注释掉了。这说明我缺乏主动重构、提取公共工具的习惯。

4、最后,注释仍然是硬伤。三次作业零注释,以后回看肯定会一脸懵。必须逼自己改掉这个坏习惯。

5.3 感悟

总的来说,这三次作业不仅是一次技术练习,更是一次思维训练。我从只会写单文件、把所有逻辑塞进 main,到能设计出 Flight、CargoCompartment、WeightBalanceCalculator 等多个类协作的小系统,这种从0到1的跨越让我真切感受到了编程能力的提升。未来我会继续保持严谨、细致的编码态度,多思考、多重构、多总结,努力写出结构更清晰、逻辑更健壮、更容易维护的代码。

posted @ 2026-05-16 17:18  Ithaca  阅读(15)  评论(0)    收藏  举报