作业集1~3的总结性Blog

一、前言

这三次作业集围绕航空器配载与货运管理这一主题展开,通过三次迭代开发,来逐步完善这个系统的功能。
第一次作业集:中等难度,核心是基础航班货运配载的面向对象设计,遵循单一职责原则,完成航班、货物、装载清单等类拆分,实现货物按重量降序装载、总重计算与超载判断,涉及封装、集合、冒泡排序和输入输出处理。
第二次作业集:中等偏难,在基础配载上迭代多货舱管理,需实现货舱、航班、调度等类,处理组合 / 聚合关系,完成货物绑定目标货舱、舱位与航班双重超载校验、多状态输出,强化输入校验与复杂业务逻辑组织。
第三次作业集:较难,聚焦航空器载重平衡计算,新增旅客、行李细粒度类,结合空机、旅客、货舱数据做力矩、重心、重心百分比换算,判断配平安全状态,需严格校验各类非法输入、容量预警并生成格式化载重平衡舱单。

二、设计与分析

(1)NCHU_航空器配载与货运管理系统1

1.类图:

image

 

本次作业共设计了6个核心类,严格遵循单一职责原则:
Flight类:仅负责管理航班信息和重量计算,提供addCargoWeight()、isOverload()等方法
Cargo类:仅负责存储货物名称和重量,是纯粹的数据载体
LoadManifest类:负责维护货物清单,体现聚合关系
CargoSorter类:独立负责排序算法,使用冒泡排序实现重量降序排列
CargoLoadService类:配载业务类,协调排序和重量累加
CargoPrintUtil类:纯输出工具类,负责格式化打印

 

2.SourceMontor的生成报表内容:

image

从SourceMonitor报表可以看出,第一次作业的代码结构较为简单:

指标数值分析
总行数 127行 代码量适中,符合入门作业规模
语句数 62条 核心逻辑清晰,无冗余代码
分支语句占比 8.1% 主要来自循环和条件判断
最大嵌套深度 4层 出现在排序算法的双层循环中
平均块深度 0.76 整体结构扁平,可读性良好

心得: 本次作业让我初步理解了单一职责原则的含义,将Flight、Cargo、LoadManifest等类职责分离,我体会到了“一个类只做一件事”带来的代码可读性提升。

(2)NCHU_航空器配载与货运管理系统2

1.类图:

image

本次作业新增和优化的类包括:
Position类:表示货舱中的一个位置(行、列),提供getPosName()方法
CargoCompartment类:货舱类,与Position是组合关系(货舱创建时内部生成Position列表),与Cargo是聚合关系
CargoWithTarget类:绑定货物与其目标货舱ID
LoadDispatcher类:调度类,负责货物按重量降序排序和查找货物
InputValidator类:输入校验类,提供整数、浮点数的范围校验方法
InputReader类:负责统一读取输入,封装Scanner操作

组合关系:Position对象的生命周期由CargoCompartment完全管理,符合组合关系的定义。

聚合关系:Cargo对象在装载前就已存在,即使从货舱中移除,Cargo对象依然存在,符合聚合关系的定义。

 

2.SourceMontor的生成报表内容:

image

根据SourceMonitor生成的报表,代码规模如下: 

指标数值说明
文件行数 324行 较第一次作业有显著增长
语句数 168条 核心逻辑密度适中
分支语句占比 11.3% 主要来自条件判断和循环控制
方法调用语句 56条 体现类间协作的频繁程度
类/接口数量 4个 类数量较少,但实际好像并非如此
每类方法数 10.00 平均每个类有10个方法,职责不够集中
每方法平均语句数 4.03 方法体较为简短
最大复杂度 4 最复杂方法的圈复杂度为4
最大嵌套深度 5层 出现在核心业务逻辑中
平均嵌套深度 1.29 整体结构较为扁平
平均复杂度 1.69 多数方法复杂度较低,易于维护
 
心得:本次作业让我深入理解了组合与聚合关系的区别。CargoCompartment与Position是组合关系——Position在货舱构造器内部创建,生命周期由货舱管理;而CargoCompartment与Cargo是聚合关系——货物从外部传入,即使离开货舱也可独立存在。正确区分这两种关系,是设计类间关联的核心。

(3)NCHU_航空器配载与货运管理系统3

 

1.类图:

image

本次作业在上一次作业的基础上,主要进行了以下变更:
新增类:
Passenger类:仅负责管理旅客行李及计算旅客总重量(含标准体重75kg),与Luggage是组合关系
Luggage类:仅负责记录行李重量,作为Passenger的组成部分
WeightBalanceCalculator类:纯计算工具类,仅负责根据航空力学公式计算总重量、总力矩、重心及百分比
修改类:
Flight类:新增List<Passenger>属性,新增getTotalPassengerWeight()等方法
CargoCompartment类:新增getArm()方法(根据货舱ID返回力臂)、getTotalWeight()方法
InputValidator类:从纯范围校验扩展为统一的输入读取+校验静态方法
Main类:输入逻辑完全重构,增加旅客行李输入、前后舱货物分别输入
删除/简化类:
CargoWithTarget类:因输入格式变化(货物按舱分类输入而非指定目标舱)而不再需要
CargoLoadExecutor类:装载逻辑简化为直接遍历前后舱货物列表

 

2.SourceMontor的生成报表内容:

image

 对报表内容的分析如下:

指标数值说明
文件行数 225行 较第二次作业反而减少,有我特意压缩行数的原因
语句数 120条 核心逻辑密度适中
分支语句占比 12.5% 三次作业中最高,主要来自配平计算的条件判断和输入校验
方法调用语句 37条 类间协作频繁度降低,得益于InputValidator的内聚设计
类/接口数量 8个 类数量适中,符合题目要求
每类方法数 3.50 平均每个类有3-4个方法,职责集中
每方法平均语句数 2.43 三次作业中最短,方法体高度精简
最大复杂度 4 最复杂方法为LoadDispatcher.sortByWeightDesc()
最大嵌套深度 5层 出现在货物装载的循环判断中
平均嵌套深度 1.78 整体结构较为扁平
平均复杂度 1.37 三次作业中最低,代码简洁高效
 
心得:第三次作业让我认识到纯计算工具类的设计要点。WeightBalanceCalculator与Flight是依赖关系而非关联关系——通过参数传递Flight对象,而不是持有Flight成员变量,这样既满足了配平计算的功能需求,又保持了计算类的独立性和可复用性。同时,InputValidator从单纯的校验方法扩展为“读取+校验”一体化的静态工具类,这种设计将输入处理的异常逻辑集中管理,大幅增强了程序的鲁棒性。

三、踩坑心得
(1)航空器配载与货运管理系统1:这次作业还是比较简单的,一个容易踩的坑是使用nextInt读取数字后,再用nextLine读取字符串,结果读取到的是空字符串。这是因为nextInt会留下一个换行符,被nextLine“吃掉”了,解决方法是每次nextInt后都加一行nextLine来消耗掉这个换行符,但题目中有相关提示和解决方法,注意审题基本不会踩这个坑;还有我因为输出内容的格式没有和题目要求完全一致,导致相关测试点没通过,我本以为是代码有什么逻辑错误或者算法问题,因此浪费不少时间;最后还有一个排序、超载测试没通过,我看两个超载测试都通过了,就觉得是排序的问题,但改来改去还是没有解决。
(2)航空器配载与货运管理系统2:题目要求CargoCompartment与Position是组合关系,意味着Position对象必须在CargoCompartment构造器内部创建,而不是从外部传入。我最初理解不够深入,试图在外部创建Position列表再传给货舱,这违反了组合关系的定义。后来我仔细阅读题目要求,发现必须在构造器内部用循环生成Position对象,这才纠正了设计;题目要求先按重量降序排序,再依次尝试将货物装入指定货舱。我的代码实现了排序,但在装载时没有体现“逐件尝试”的过程。从测试结果看,部分测试点失败,我不知道失败的测试点是测试什么的,但我怀疑可能是因为我在装载失败时的处理逻辑有误,只是目前还没有解决;我还是要提一下注意输出格式的问题,建议直接从题目里复制过来,确保格式没错,当然,类似总重量值之类的不能直接复制,建议结合输出样例去理解。
(3)航空器配载与货运管理系统3:一开始我只通过了一半的测试点,之后最先解决的是装载货物重量数据非法测试的问题,就是一个最小值的设置,我一开始设置的是0,后来改成1就通过了,我感觉是题目没说清楚;然后剩下的测试点基本是一起解决的,但我是一次性改了两处错误,一个是装载货物的部分,关于调用排序的问题,另一个是经典的输出格式,主要是题目没说的很清楚,加上只有一个数据无误评估安全的样例,导致我不确定数据有误的输出是怎样的,就试了几种情况,好在可能性就几种,最后通过了全部的测试点。
四、改进建议
(1)第一次作业中,我在Main类中直接使用Scanner进行输入读取,导致代码中多处出现sc.nextLine()处理换行符的逻辑。这种分散的处理方式增加了出错的可能性。改进建议是将所有输入读取操作封装到一个独立的InputReader类中,统一处理换行符问题,使Main类更加简洁。还有我的代码采用的是先累加所有货物重量,再统一判断超载的方式。但题目要求“系统需实时计算当前已装载的总重量”,这意味着每添加一件货物后就应该判断一次。改进方向是在addCargoWeight方法中增加实时判断,当累计重量超过最大载重时立即给出警告,而不是等到所有货物添加完毕。
(2)第二次作业中,我的InputValidator类只提供了范围校验的静态方法,但没有主动读取输入。改进建议是将输入读取和校验合并在一个方法中,例如定义一个readIntWithRange方法,在读取整数的同时进行范围校验,这样可以减少Main类中的重复代码。
(3)第三次作业中,WeightBalanceCalculator类是纯计算工具类,其核心方法是generateLoadSheet。该方法包含了配平计算的全部五个步骤,代码量较大且逻辑密集。改进建议是将五个计算步骤拆分为独立的私有方法,如calculatePassengerMoment、calculateCargoMoment、calculateTotalWeight等,每个方法只负责一个计算步骤。这样既可以提高代码可读性,也便于单独测试每个计算步骤的正确性。我的代码中大量使用了System.exit(0)来终止程序,这种做法虽然简单直接,但不便于扩展。改进建议是定义一个自定义异常类,如InputValidationException,当检测到非法输入时抛出该异常,在Main类中统一捕获并处理。
五、总结
通过这三次航空器配载与货运管理系统的编程作业,我逐步掌握了 Java 面向对象编程的核心思想,深入理解了单一职责原则(SRP)在实际编程中的应用,学会了根据业务需求拆解功能、设计独立且职责清晰的类结构,如将航班、货舱、货物、旅客等实体分层设计,同时掌握了冒泡排序算法的手动实现、数据输入校验、异常处理以及基础的物理力矩、重心百分比等航空配载业务逻辑,也熟练运用了集合存储数据、格式化输出结果等编程技巧。
在学习过程中,我也发现自身存在不足:一是对复杂业务场景下的类间关系(组合、聚合)理解不够透彻,设计类结构时偶尔会出现职责混淆的问题;二是代码的健壮性和扩展性有待提升,面对边界条件和异常输入时,处理逻辑不够完善;三是涉及到复杂一些的业务逻辑时,难以将其与代码实现高效地结合。
至于改进建议:我先想到了这几次作业集,主要是第三次作业集,我感觉这输入输出样例只有一个不太合理,特别是这次题目还挺复杂,虽然题目中有说其他情况的输出格式,但我觉得最好还是再加几个样例好些,希望以后的作业集注意这点,暂时只想到这个。
posted @ 2026-05-18 23:37  5926  阅读(12)  评论(0)    收藏  举报