面向对象设计与构造——作业集1~3总结
面向对象设计与构造——作业集1~3总结
一、前言
这三次作业围绕航空货运配载和载重平衡展开,从最开始只有一个货舱的货物管理,慢慢扩展成多货舱,又加了旅客和行李,最后还要算重心、力矩、重心百分比,生成载重平衡仓单。作业难度逐级增大,每次都在上次基础上加新东西。题量不算大,但每一轮都要考虑设计类的关系。通过这三次作业,我确实学到了不少:
1、Java基础语法运用,包括类与对象的定义、属性和方法的封装、数组和集合的基本操作;
2、单一职责原则(SRP)的实际运用,学会了怎么把不同功能的代码拆到不同的类里;
3、类之间的组合、聚合、依赖,搞清楚了什么时候用new,什么时候用引用传递;
4、输入输出的规范化处理,包括Scanner的换行符处理、小数位数控制、输出格式对齐;
5、数组的相关方法的运用,数组边界的检测,还有ArrayList和数组之间的转换。
二、设计与分析
第一次作业
作业要求:实现基础版的货运配载,管理一个货舱,货物按重量从高到低排序,统计总重量并判断是否超载。要求严格遵循单一职责原则。
实现方式:我拆了5个类。Main负责读输入和调度;Flight存航班号、最大载重、当前总重;Cargo是货物实体;CargoSorter专门做选择排序;LoadManifest负责输出装载清单。货物用数组存,总重量循环累加。拆完之后每个类都很短,哪里出问题一眼就能看到。
代码规模:第一次作业代码规模小、结构清晰,但缺少注释,最大复杂度7处在可接受范围,后续作业需关注深层嵌套的优化。

类图:类图结构符合单一职责原则,各类职责边界清晰,聚合关系使用恰当。

复杂度分析:所有方法复杂度在1~7之间,没有超过10的危险阈值。CargoSorter的sortByWeightDesc()是唯一需要关注的方法,后续作业可考虑将其拆分为更小的步骤方法以降低复杂度和嵌套深度。

Bug分析:
1. 公测:nextInt()后未处理换行符,导致货物名丢失;冒泡排序不稳定,同重量货物输出顺序不一致,后改为选择排序。
2. 互测:货物数量为0时未输出空清单格式,与题目要求不符。
3. 测试方法:通过测试不同的输出情况,对代码进行调试。
第二次作业
作业要求:升级成多货舱,每个货舱有独立ID、最大载重、位置网格。货舱和位置是组合关系,货舱和货物是聚合关系。货物按重量降序装入指定货舱,分别检查货舱和航班是否超载。强制实现6个核心类。
实现方式:增加了Position、CargoCompartment、InputValidator、LoadDispatcher。用ArrayList存货舱和货物,遍历找货舱ID。排序保证同重量货物按输入顺序不变。校验类统一检查非负。每个货舱自己维护当前重量并判断超载。输入校验单独抽出,便于复用。
代码规模:从报告来看,第二次作业共7个文件、149条语句,平均每个类3.43个方法,比第一次的1.20更合理。最大复杂度为4,出现在LoadDispatcher.sortCargos(),比第一次的7有所下降。最大深度5,平均深度1.83,平均复杂度1.57,整体指标优于第一次。
最复杂方法是sortCargos()(复杂度4、深度5),承担货物排序分配逻辑;findCompartmentById()和findCargo()复杂度3,负责查找;其余getter/setter复杂度均为1。注释百分比仍为0%,需要改进。
块深度分布:深度2有64条语句(最多),深度4有4条,深度5有1条,嵌套程度适中。
Kiviat图显示:平均复杂度从3.00降至1.57,每类方法数从1.20增至3.43,最大复杂度从7降至4,代码质量明显提升。

类图:Flight聚合CargoCompartment列表,CargoCompartment组合Position(实心菱形)并聚合Cargo(空心菱形)。Main依赖InputValidator和LoadDispatcher工具类。各类职责清晰,组合与聚合语义准确。

复杂度分析:
复杂度1:各类getter/setter、构造方法、addCompartment()、validateDouble()等,共约15个方法。
复杂度2:addCargo()、getCurrentWeight()、getTotalWeight()、validateInt(),含简单判断或累加逻辑。
复杂度3:CargoCompartment构造方法、findCompartmentById()、findCargo(),含遍历查找或多步初始化。
复杂度4:sortCargos()(语句数11、深度5、调用10),核心排序分配逻辑,可接受但后续可拆分。
小结:所有方法复杂度1~4,最大复杂度比第一次降低,但注释仍为0%,需加强

Bug分析:
1. 公测:货舱ID查找未做空判断,导致空指针异常;超载状态判断逻辑写反。
2. 互测:排序未保证同重量货物的输入顺序;输出小数位数不统一。
3. 测试方法:通过测试不同的输出情况,对代码进行调试。
第三次作业
作业要求:加上旅客和行李,旅客和行李是组合关系。要算力矩、总力矩、实际重心、重心占MAC百分比。输入严格校验,负数或越界直接终止。前后舱分别校验最大载重。禁止用继承、接口、多态,排序必须手写冒泡排序。输出标准化舱单并评估重心是否安全。
实现方式:增加了Luggage、Passenger、WeightBalanceCalculator。旅客类内实例化行李,强组合。计算类为纯静态方法,只接收Flight对象。冒泡排序手写,校验类检查整数、浮点数、范围、货舱容量。
代码规模:第三次作业共8个文件、257条语句,注释百分比首次达到1.6%。平均每类6.44个方法,平均每个方法2.72条语句,方法划分更细。最大复杂度7(Main.main()),最大深度5,平均复杂度1.24,为三次最低。
最复杂方法是Main.main()(复杂度7、语句49),承担输入读取和流程控制,偏复杂;printBalanceEvaluation()和sortCargos()复杂度4;其余大量getter/setter复杂度均为1。
块深度分布:深度2有113条语句(最多),深度3有56条,深度4仅3条,比前两次有所改善。
Kiviat图显示:平均复杂度1.24为三次最低,每类方法数6.44为三次最高,注释从0%提升到1.6%是明显进步。

类图:Flight管理货舱列表和旅客列表;CargoCompartment分前后舱,管理货物;Cargo存货物信息;Passenger存旅客及行李;LoadDispatcher负责排序;InputValidator负责校验;WeightBalanceCalculator负责重心计算和舱单输出。各类职责明确。

复杂度分析:
复杂度1:约40个方法,包括各类getter/setter、构造方法、addCargo()、calculateCG()等。
复杂度2:checkInt()(语句4、深度3),含简单校验。
复杂度4:LoadDispatcher.sortCargos()(语句9、深度5、调用10)、printBalanceEvaluation()(语句7、深度3、调用4)。
复杂度7:Main.main()(语句49、深度4、调用8),是三次作业中最复杂的单个方法,建议后续拆分。
小结:所有方法复杂度1~7,main方法需重点优化。注释百分比首次突破0%,仍需加强。

Bug分析:
1. 公测:使用了排序,输出结果错误。
2. 互测:负数输入校验未生效;冒泡排序循环边界写反,导致排序乱序。
3. 测试方法:通过测试不同情况下的输出,结合输出的结果,对代码进行调整。
三、踩坑心得
三次作业下来,踩了不少坑,覆盖输入处理、数据校验、算法逻辑、边界场景、输出格式、类设计耦合等方面。
Scanner的换行符问题三次都遇到了。统一在数值输入后加sc.nextLine()吸收换行符解决。
空指针和边界数据也是重灾区。第二次作业找货舱ID没做空判断直接崩了。后来养成遍历前判空、下标访问前校验的习惯。
单一职责原则一开始没贯彻好。第一次作业把排序、输出、校验全塞在Main里,代码混乱。拆类后可读性和维护性明显提升。
排序稳定性需要留意。第一次作业冒泡排序实现不稳定,相同重量货物顺序与预期不符,说明实现不能只求“能跑通”。
类间耦合方面,直接访问其他类的内部变量导致改一处牵连多处。改用getter/setter或专门方法交互,降低耦合。
数组边界检测也容易犯错。总结套路:遍历前判空,下标访问前确认合法范围,查找方法返回null时调用方必须判断。
四、改进建议
结合这三次作业的踩坑经历,我觉得可以从几个方向改进一下(结合ai的建议):
常量统一管理:空机重量、力臂、MAC参数等硬编码,可集中定义为public static final常量类,便于维护。
异常处理优化:非法输入直接System.exit(0)不规范,可自定义异常并用try-catch给出友好提示。
货舱和机型适配:固定前后舱可改为动态读取货舱配置,支持不同机型。
排序和数据结构:小数据量下手写排序可行,后续可结合Collections.sort(),并用缓存变量优化重量统计。
注释和单元测试:为核心类和方法添加注释,引入JUnit对排序、重心计算等编写自动化测试。
数据持久化和可视化:可将舱单输出为txt文件保存,后续可加简单图形界面实时查看重心变化。
输入校验的完善:目前只做了非负和范围校验,还可增加货舱ID格式、货物名称长度、航班号格式等校验。
日志记录:记录货物装载、重心计算等关键操作,便于问题追溯。
五、总结
通过这三次作业,我从过程式编程逐步过渡到合理拆分类、设计类关系、处理复杂业务逻辑。基本掌握了单一职责原则、组合/聚合/依赖、高内聚低耦合等设计概念,并在代码中实际运用出来。
同时认识到自身不足:算法边界处理不够严谨,异常校验能力偏弱,自动化测试意识薄弱。后续将加强注释、单元测试、常量类和异常处理,进一步提升代码质量。
整体来说,这三次作业梯度合理,每次在上一轮基础上增加复杂度,有效锻炼了面向对象设计与构造能力。
浙公网安备 33010602011771号