三次作业的总结
前言
本次三段式作业集围绕“航空器货运配载与载重平衡”这一真实业务场景展开,从基础的单货舱超载判断,迭代到多货舱管理,最终引入旅客与重心(CG%)计算,完整模拟了航空公司配载系统的核心功能。
知识点覆盖:
第一次作业:类与对象、List容器、选择排序、单一职责原则(SRP)
第二次作业:多类协作、组合与聚合关系、输入校验、冒泡排序
第三次作业:力臂力矩计算、百分比换算、数据验证、业务逻辑与UI分离
题量与难度:
三次作业代码行数从约120行增长到约350行,类的数量从3个增加到10个左右。第一次较直观,第二次需要理解货舱与位置的组合关系、货物与货舱的聚合关系,第三次加入物理公式和严格的输入合法性检查。难度逐次上升,但每次迭代都有清晰的增量说明,过渡平滑。
个人感受:第三次作业虽然计算逻辑复杂,但由于前两次已经打好货舱管理的基础,主要挑战在于理解“力矩”和“MAC百分比”概念,并将其准确转化为代码。
设计与分析
以下结合我三次作业的实际源码和类图,分析每次的设计思路、SRP遵循情况以及存在的问题。
第一次作业:基础货运配载

类图结构:
Hangban:记录航班号、最大起飞重量、最大业载重量
Huowu:货物名称、重量
Zhuangzai:管理货物的添加、排序(选择排序)、总重量计算、超载判断
Main:输入处理和调用
分析:
本次作业要求“按货物重量从高到低向该航班添加货物”,我使用了选择排序对List
亮点:
货物添加后实时计算总重量,判断是否超过maxWeight
保留了Hangban中的maxTakeoffWeight和maxPayload两个字段,虽然本次未完全使用,但为后续迭代预留了扩展点
不足:
Zhuangzai类命名不够语义化,用cargoManager可能更好
变量命名使用了单字母(a,b,c,d,e,f,g),降低可读性
第二次作业:多货舱管理与重量排序装载

题目要求设计Position、Cargo、CargoCompartment、Flight、LoadDispatcher、InputValidator六个核心类,严格遵循SRP。但我提供的代码并未遵循题目给定的类图,而是自己设计了一个简化版本(只有FeijiHuoCang和Huowu两个类,且固定为左右两舱)。
实际代码中的问题:
没有Position类,货舱的行列信息未被利用
没有LoadDispatcher,排序逻辑直接写在FeijiHuoCang内部
没有InputValidator,输入校验散落在各处
货舱ID硬编码为“左舱”“右舱”,无法扩展到两个以上货舱
正确设计应该是什么样?
根据题目类图,CargoCompartment内部应new出Position对象列表(组合关系),并聚合Cargo列表。LoadDispatcher负责对货物按重量降序排序,然后逐一调用CargoCompartment.addCargo()。InputValidator用静态方法提供getInt()、getDouble(),处理负数或超范围的输入。
这次作业给我的教训:
不能只看题目描述就动手写代码,一定要仔细阅读类图和设计要求。题目明确写道“违背SRP此题不得分”,而我提交的代码把排序、装载、输出全部塞在一个类里,严重违背原则。虽然运行结果正确,但在设计评价上是不合格的。
第三次作业:配平计算

第三次作业在前两次基础上增加了Passenger、Luggage、WeightBalanceCalculator、InputValidator(完善版),以及原有的Flight、CargoCompartment等。我提交的代码基本遵循了题目要求,并且正确实现了力矩计算和MAC百分比转换。
类图与代码对照:
Passenger与Luggage是组合关系:Luggage对象在Passenger构造器内new出,符合要求
WeightBalanceCalculator没有持有Flight成员变量,所有方法都是静态的,generateLoadSheet(Flight flight)作为入口,符合依赖关系
InputValidator思想已体现,但实际代码中仍在main里用if(负数)直接判断,没有完全抽取成独立类
排序使用了冒泡排序(ZhuangZaiDiaoDuQi.paiXuHuoWuAnBianHaoShengXu),满足“不允许使用lambda和Collections.sort()”的要求
力矩计算核心代码:
全机总力矩 = 空机重量×空机力臂 + 旅客总重×旅客力臂 + Σ(货舱重量×货舱力臂)
实际重心 = 全机总力矩 / 全机总重量
CG% = ((实际重心 - MAC前缘距离) / MAC长度) × 100%
设计亮点:
将计算逻辑全部放在ZhongLingPingHengJiSuanQi中,主流程只负责输入和组装对象
货舱力臂通过id判断(1→12.0,2→22.0),虽然有点硬编码,但符合题目给定常量
输出格式完全参照样例,包含【基础数据】、【旅客数据】、【货物数据】、【汇总计算】、配平评估五个区块
不足之处:
输入校验没有统一使用InputValidator,导致main方法中仍有重复的校验代码
没有使用Position类,货舱的行列信息只读入但从未使用(题目要求是“生成位置网格”,实际代码未体现)
采坑心得
- Scanner的nextLine()陷阱(第一次作业)
题目特别提示了nextInt()后要加一个nextLine()吃掉回车,否则后续nextLine()会读空字符串。我在代码中使用了Double.parseDouble(scanner.nextLine())的方式统一处理,避免了混用nextInt()/nextDouble()与nextLine()的问题。这种方法更安全。 - 货舱超载的判断时机(第二次作业)
我最初的做法是先将所有货物加入货舱列表,最后再判断是否超载。但正确的需求是:每次添加一件货物前就要检查,若超载则拒绝并提示。修改后逻辑:
if (当前重量 + 货物重量 <= 最大载重) {
添加;
} else {
输出警告并退出;
} - 旅客总重计算错误(第三次作业)
我最初写成了旅客总重 = Σ(75 + 行李),但题目要求单名旅客总重 = 75 + 行李重量,这个容易理解。真正踩坑的是旅客的行李重量输入顺序:输入样例中前三个数值100、200、80对应三位旅客的行李重量,我误以为是每行输入“姓名 行李重量”,但题目实际只给行李重量,不需要姓名。这点在LvKe构造器中直接传入行李重量即可。 - CG%安全范围判断的浮点精度
安全范围是25.0~38.0,计算出的CG%可能由于浮点运算得到24.9999,我最初直接用if(cg < 25.0),导致本应安全的判定为危险。修改为加入极小容差:
if (baiFenBi >= 25.0 - 1e-6 && baiFenBi <= 38.0 + 1e-6) - 货物排序算法选择
第二次作业要求“按重量降序”,第三次作业又要求“按货物编号升序(冒泡排序)”。我两次都使用了选择排序/冒泡排序,未使用Collections.sort(),虽然代码量稍多,但符合题目限制。心得:手写排序时要特别注意边界条件,j < n - i - 1容易写错成j < n - i导致数组越界。
改进建议
彻底遵循SRP,拆分过大的类
第一次作业的Zhuangzai、第二次作业的FeijiHuoCang都应该拆分。例如:
CargoSorter:仅负责排序
CargoLoader:仅负责将货物分配到货舱
ReporPrinter:仅负责输出各类报表
引入InputValidator统一校验
第三次作业中main方法里散落着大量if(负数) exit,应改为:
int num = InputValidator.getPositiveInt(sc, "请输入正整数");
double weight = InputValidator.getNonNegativeDouble(sc, "请输入非负数");
这样既减少重复代码,也便于统一修改提示语。
使用枚举或常量管理货舱力臂
第三次作业中用if(id1)分配力臂,扩展性差。可以定义:
public enum CargoBay {
FORE(1, 12.0), AFT(2, 22.0);
private int id;
private double arm;
}
新增货舱时只需增加枚举项。
完善Position类的使用
第二、三次作业都要求生成位置网格(行×列),但实际代码未实现。可以这样做:
class Position {
private int row, col;
private boolean isOccupied;
public String getPosName() { return row + "-" + col; }
}
在CargoCompartment构造器中生成List,装载货物时标记占用。 或精确不等号,需要容差
业务逻辑与IO彻底分离
目前WeightBalanceCalculator内部直接System.out.println,导致无法复用(例如未来需要生成JSON报告或图形界面)。应改为返回一个BalanceReport对象,由调用方决定如何展示。
总结
通过这三次作业,我完整经历了一个需求迭代驱动设计演进的过程:
第一次学会了基本的类设计和排序算法,但忽视了单一职责原则
第二次理解了组合与聚合的区别,也深刻体会到“不看类图就写代码”的后果
第三次掌握了力矩计算和重心百分比转换,并成功将物理公式落地为代码
学到了什么:
SRP不仅仅是理论,它直接影响代码的可维护性和可测试性
迭代开发中,前一次的设计缺陷会在后一次被放大,因此基础要打
输入校验必须统一、前置,不能等到计算时才发现问题
浮点数比较不能直接用
需要进一步学习的:
设计模式(如策略模式用于不同排序规则,工厂模式用于创建货舱)
单元测试(JUnit),验证力矩计算在各种边界条件下的正确性
异常处理体系,而不是简单System.exit(0)
对课程的建议:
作业难度梯度设置合理,由浅入深,每次迭代都有明确的新增要求,很适合初学者
希望能提供标准答案的类图与代码,让我们对比自己的设计差距
建议增加一次“代码重构”环节,在第三次作业完成后,要求我们将前三次代码按SRP彻底重构一次,加深理解
这次博客总结让我重新审视了自己的代码,发现了许多可以改进的地方。在今后的编程中,我会更加注重设计先行,而不仅仅是让程序“跑起来”。

浙公网安备 33010602011771号