第二次Blog作业:对航空货运管理系统总结
一、前言:从基础建模到复杂业务的迭代
题目集 8 和 9 以 “航空货运管理系统” 为核心,构建了从基础类设计到复杂业务逻辑实现的完整训练路径。题目集 8 侧重基础功能搭建,包含客户信息管理、货物计费、航班载重检查等核心模块,共 3 道题目,难度以 “类的封装与简单交互” 为主。题目集 9 则在此基础上引入客户类型折扣、多货物类型费率、多支付方式等复杂规则,题目数量缩减为 2 道,但要求更高的系统扩展性和代码健壮性。
从知识点覆盖看,两次题目集贯穿了面向对象编程的核心概念:
类的封装与继承:题目集 9 通过抽象类 Customer 派生出 IndividualCustomer 和 CorporateCustomer,实现不同客户类型的折扣策略。
多态与接口:题目集 9 定义 PaymentMethod接口,通过 WechatPayment/AlipayPayment/CashPayment实现多态,解耦支付逻辑。
枚举与策略模式:题目集 9 使用 CargoType枚举区分货物类型,并通过策略模式(Cargo类内的switch-case)实现不同类型货物的费率计算。
异常处理与代码健壮性:题目集 9 通过工厂方法(parseCargoType/parsePaymentMethod)处理非法输入,相比题目集 8 的 “裸奔代码” 有明显改进。
二、设计与分析:从代码实现到架构演进
题目集 8:本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则,程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表。
题目集 8 的系统由 5 个核心类构成,类间关系通过 “关联” 和 “聚合” 实现:
Customer类:封装客户基础信息(ID、姓名、电话、地址),但仅提供getName()和getPhone()方法,未预留扩展接口(如客户类型区分),导致题目集 9 需重构为抽象类。
Cargo类:
核心逻辑:通过构造方法计算计费重量(calculateChargeableWeight())和费率(硬编码的if-else判断),将业务规则封装在类内。
问题:费率计算与货物类型强绑定(题目集 8 仅支持普通货物),若新增危险品或加急件,需直接修改类代码,违反开闭原则。
Flight类:
负责航班载重管理,通过addCargo()方法检查货物重量是否超过最大载重(maxLoad)。
局限:未考虑货物优先级(如加急件需优先装载),仅实现 “先到先装” 的简单逻辑。
Order类:
整合订单信息,通过displayOrderDetails()方法输出详情,直接依赖Customer和Flight类,耦合度较高。
支付方式固定为微信支付(PaymentMethod类硬编码),缺乏扩展性。
代码质量与设计缺陷
圈复杂度分析:
Cargo类的构造方法包含计费重量计算和费率判断,圈复杂度约为 6(1 个循环 + 5 个条件分支)。
Order类的displayOrderDetails()方法包含大量System.out.printf语句和循环,圈复杂度约为 8,代码可读性差。
类图:

关键缺陷:
硬编码问题:费率、支付方式等业务规则直接写入代码,如Cargo类中 “if (weight < 20) rate = 35”,导致需求变更时需修改底层类。
缺乏抽象层:客户类型、支付方式等可变点未抽象为接口或抽象类,系统扩展性受限。
异常处理缺失:未对输入数据(如负数重量、空字符串)进行校验,程序易崩溃。
题目集 9:本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则、依赖倒转原则,程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表。
题目集 9 的航空货运管理系统采用了面向对象设计的思想,通过抽象类、接口、枚举等机制实现了系统的可扩展性和可维护性。
客户类型的多态实现:
定义抽象类Customer,通过IndividualCustomer和CorporateCustomer子类实现不同的折扣策略利用多态机制,在Order类中customer.getDiscountRate()动态调用子类方法符合开闭原则,新增客户类型(如 VIP 客户)时无需修改现有代码。
支付方式的接口化设计:
定义PaymentMethod接口,通过WechatPayment、AlipayPayment、CashPayment等具体类实现不同支付方式使用工厂方法parsePaymentMethod()创建支付方式对象实现了支付逻辑的解耦,支持后续扩展其他支付方式。
货物类型的枚举应用:
使用CargoType枚举定义 NORMAL、EXPEDITE、DANGEROUS 三种货物类型在Cargo类中根据不同类型实现差异化的费率计算相比题目集 8 的硬编码方式,提高了代码的可维护性。

客户相关类:

通过抽象类Customer定义公共属性和抽象方法,强制子类实现折扣率计算,子类IndividualCustomer和CorporateCustomer实现具体折扣策略,符合单一职责原则。不足之处在于折扣率硬编码在子类中,若后续折扣规则变化需修改子类代码。
货物相关类:

使用枚举CargoType简化了货物类型的管理,在getRate()方法中根据不同货物类型实现差异化费率计算。存在的问题:费率计算逻辑复杂,嵌套多层条件判断,降低了代码可读性,若新增货物类型,需要修改getRate()方法,违反开闭原则,计费规则与货物实体类耦合,不利于规则的灵活变更。
航班类:

职责明确,专注于航班信息管理和载重控制,使用LocalDate代替字符串表示日期,提高了类型安全性,提供addCargo()方法检查并更新航班载重状态。不足之处在于没有考虑货物优先级和航班空间利用率问题。
支付相关类:

通过接口PaymentMethod定义支付方式的公共行为,具体支付类实现接口,符合依赖倒置原则,使用工厂方法parsePaymentMethod()创建支付对象,实现了对象创建和使用的分离。不足:仅实现了支付方式的名称获取,未涉及实际支付处理逻辑。
订单类:
整合了订单所需的所有信息和操作,通过依赖Customer和PaymentMethod接口实现多态,提供了计算原始运费和最终运费(含折扣)的方法displayOrderDetails()方法负责格式化输出订单信息。存在的问题:订单信息展示逻辑与业务逻辑耦合,缺乏订单状态管理功能。
三、采坑心得:从代码调试到设计反思
在Order.displayOrderDetails()方法中调用flight.getFlightNumber()时崩溃。

解决方案:在方法入口添加空值检查
if (flight == null) {
System.err.println("错误:航班信息为空");
return;
}
枚举类型拼写错误引发的运行时异常,在输入枚举类型时没有全部大写,导致IllegalArgumentException。
输入验证与异常处理的缺失
题目集 8 未校验货物重量为负数,导致calculateChargeableWeight()返回负数,程序逻辑错误。
题目集 9 的parseCargoType()方法未处理拼写错误(如输入 “NORMAl”),直接抛出未捕获的IllegalArgumentException,导致程序终止。
四、改进建议
问题:输入非法数据(如负数重量)时程序崩溃
改进方案:在Cargo构造方法中添加参数校验
增加注释与文档:
在Cargo类的calculateChargeableWeight()方法中添加注释,说明 “体积重量按 6000cm³/kg 换算” 的行业标准。
为Flight类的addCargo()方法添加 Javadoc,说明 “返回值表示是否装载成功” 的语义。
提取重复代码:
题目集 9 的Order类displayOrderDetails()方法中,地址、电话等输出语句重复,可提取为printContactInfo()辅助方法。
五、总结
抽象与多态的力量:通过题目集 9 的Customer抽象类和PaymentMethod接口,理解了如何通过多态实现 “行为扩展而不修改现有代码”。例如,新增企业客户类型时,只需继承Customer并实现折扣率,无需改动Order类的计费逻辑,直接体现了开闭原则。
封装的边界把控:在Cargo类中,将计费重量计算封装为私有方法calculateChargeableWeight(),确保外部无法直接修改计算逻辑,同时通过公共方法暴露必要属性(如getChargeableWeight()),平衡了数据安全性与访问便利性。
接口隔离的价值:题目集 9 的PaymentMethod接口仅定义getPaymentName(),虽功能单一,但为后续扩展支付核心逻辑(如pay()方法)预留了空间,避免了 “胖接口” 问题。
通过题目集 9 的客户类型和支付方式设计,深刻理解了多态的本质 ——同一接口,不同实现。例如:
Customer抽象类定义getDiscountRate()接口,IndividualCustomer和CorporateCustomer实现不同折扣策略,代码中仅需通过customer.getDiscountRate()调用,无需关心具体子类。
PaymentMethod接口将支付方式抽象为getPaymentName(),微信、支付宝等具体类实现细节,使Order类与支付方式解耦,新增支付方式时只需实现接口,符合开闭原则。
在绘制题目集 9 类图时,明确了类间关系(如Order与Customer的关联、Cargo与CargoType的组合),我学会用 UML 工具表达抽象类、接口和枚举的层次结构,提升了系统设计的可视化能力。

浙公网安备 33010602011771号