NCHU_OOP航空货运管理系统总结
前言
航空快递以速度快、安全性高成为急件或贵重物品的首选,此次作业涉及到航空货运管理系统的设计与实现,主要涉及到了Java语言的面向对象编程思想,以及一些常用的设计模式。
设计与分析
第一次作业分析
题目分析
本次作业要求实现一个航空货物托运系统,能够根据客户、货物、航班等信息计算运费并输出订单详情。
核心功能包括
- 收集客户、货物、航班、订单等信息
- 计算货物计费重量(体积重量与实际重量取较大值)
- 根据重量分段计算运费(不同重量区间对应不同费率)
- 校验航班承载能力,输出订单详情或报错信息
除了实现以上功能,同时还需要遵循单一职责原则、里氏代换原则、开闭原则以及合成复用原则,
输入格式 :
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
输出格式 :
- 如果订单中货物重量超过航班剩余载重量,程序输出
The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order.,程序终止运行。 - 如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
-----------------------------------------
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
注:输出中实型数均保留1位小数。
设计
架构设计
- 数据模型层:定义
Good(货物)、Person(作为抽象父类)、Flight(航班),Order(订单)。其中Receiver(收件人)、Sender(发件人)、Customer(客户)作为子类继承Person,通过以上类封装业务数据 - 接口层:
Weightable:定义获取计费重量的接口calculatable:定义计算总费用的接口
- 业务逻辑层:
Agent类负责计算总重量和总费用,主程序处理输入输出
关键逻辑设计
- 计算总重量
// Good类中实现Weightable接口
public double getWeight() {
double volweight = length * width * height / 6000;
return Math.max(volweight, weight); // 取体积重量与实际重量的较大值
}
-
运费分段规则

- 在Agent.calculatebill()中通过if-else实现分段计费。
代码分析
优点
1.经过新一轮的学习后,本次作业通过继承和接口实现了代码复用,如Customer、Sender、Receiver继承Person共享通用属性,遵循了依赖倒置原则(DIP)。
2.使用了LocalDate类处理日期,避免了字符串转换的开销,提高了程序对时间信息处理的效率。
缺点
1.此次作业把运费分段的阈值和费率直接写死在代码中,缺乏可维护性。
2.未校验重量、尺寸等参数是否为负数或零,可能导致业务逻辑错误。
3.对继承与接口的理解不够深入,导致代码结构不够清晰,存在代码冗余。
SourceMonitor分析

从报表数据来看,平均复杂度(Avg Complexity)较高,在算法优化上存在不足导致消耗大量资源,但是平均深度,最大深度以及最大复杂度均位于绿色圈内,但是注释率较低,存在代码注释不足的问题,需要在算法优化上进行改进。
类图

从类图来看,此次编写的系统结构仍然较为简单,实现了类的继承与接口的实现,但是存在大量可优化的空间。
第二次作业分析
题目分析
此次作业在第一次作业基础上新增需求:
- 客户类型:区分个人(Individual)和企业(Corporate),分别享受 9 折和 8 折优惠。
- 订单类型:新增普通(Normal)、加急(Expedite)、危险品(Dangerous)类型,不同类型对应不同费率(如加急件费率更高)。
- 支付方式:支持支付宝、微信、现金支付,输入英文自动转换为中文(如Wechat→微信)。
设计
架构改进
- 新增属性:
- 在Customer类中添加
customerType:客户类型(Individual/Corporate),在Agent.calculatebill()中根据客户类型计算折扣。 - 在Order类中添加
orderType:订单类型(Normal/Expedite/Dangerous),在Agent.calculaterate()中根据类型和重量计算单件费率。 - 通过Payable接口定义支付行为
payType:支付方式(Alipay/Wechat/Cash)
- 在Customer类中添加
- 数据结构改进:
- 引入
Ordercategory(订单项类),关联Good对象并存储计费信息(rate、price),实现Weightable接口。 Order类聚合Ordercategory列表,不再直接关联Good,提升模块化程度。
- 引入
关键逻辑改进
- 关键逻辑扩展
- 费率计算:

// Agent.calculaterate()中根据订单类型和重量设置费率
if (a.getWeight() >= 100) {
if (order.getType().equals("Normal")) a.setRate(15);
else if (order.getType().equals("Expedite")) a.setRate(30);
// ...其他类型
}
- 客户折扣:
// Agent.calculatebill()中应用折扣
if (order.getCustomer().getCustomerType().equals("Individual")) total *= 0.9;
else if (order.getCustomer().getCustomerType().equals("Corporate")) total *= 0.8;
代码分析
优点
1.通过引入Ordercategory类,实现了订单与货物的解耦,提高了代码的可维护性和扩展性,结构更加清晰。
2.新增客户类型和订单类型时,只需修改Agent类逻辑,未破坏原有代码结构。
3.定义Payable接口及实现类(如Alipay),符合开闭原则,为后续支付功能预留空间。
缺点
1.对费率的计算依然使用多层if-else嵌套,不够灵活,可能导致代码冗余而且可读性差,维护成本高。
2.对Payable接口的实现类没有编写实际的支付逻辑,知识面不够,无法完成支付功能。
SourceMonitor分析

从报表数据来看,经过迭代,平均复杂度大幅降低,存在代码注释不足的问题。
类图

经过迭代后,类图更加清晰,Ordercategory类与Order类之间的聚合关系更加明显,整个系统更加模块化,易于维护和扩展。
踩坑心得
-
输入信息时会发生
java.util.InputMismatchException异常,原因是连续使用nextInt()和nextLine()时,需用in.nextLine()手动清空换行符,否则会导致输入错位。

-
需要仔细琢磨题目意思,如“重量”指的是计费重量,而不是实际重量,理解错误会导致程序逻辑错误,导致答案错误。
-
在使用
LocalDate类处理日期时,需注意日期格式的正确性,避免出现DateTimeParseException异常。
改进建议
- 在输入信息时,增加输入校验,如检查输入是否为数字、日期格式是否正确等,避免程序崩溃。
- 对于费率计算,可以考虑使用策略模式,避免使用多重if-else嵌套,根据不同的订单类型和重量计算费率,提高代码的可维护性和扩展性。
- 对于支付方式需要经过学习后,实现实际的支付逻辑,如调用第三方支付接口等以实现支付。
- 可以尝试使用工厂模式,根据不同的订单类型创建对应的订单对象,提高代码的可扩展性和可维护性。
- 对于异常处理,可以尝试根据不同的错误类型抛出不同的异常,提高代码的可读性和可维护性。
总结
两次作业通过逐步扩展业务需求,深入实践了 Java 面向对象设计的核心原则。第一次作业建立了基础的数据模型和流程,第二次作业通过新增维度(客户类型、订单类型)和优化数据结构(引入Ordercategory)提升了系统的灵活性,但是在费率计算和支付方式实现上仍存在不足,存在代码冗余和扩展性不足的问题。
通过本次作业,我对面向对象设计模式有了更深入的理解,对接口和抽象类的使用有了更加深入的认识,同时也对 Java 语言的特性有了更深入的认识。在后续的学习中,我将继续努力提高代码质量,提高代码的可读性和可维护性,以适应更复杂的业务需求。

浙公网安备 33010602011771号