UnKn0wN-XD

 

Java两次航空货运管理系统blog

一、前言
在两次题目集的设计与实现中,我们完成了“航空货运管理系统”的基础版与扩展版开发。题目集从简单订单管理逐步升级为支持多类型货物、客户分类及支付方式的复杂系统,涉及知识点包括面向对象设计、集合框架应用、策略模式实现、输入输出处理等。以下从设计与分析、采坑心得、改进建议等方面展开详细探讨。

二、设计与分析

  1. 系统架构演进
    题目集1(基础版):

核心类:Client(客户)、Air(航班)、Deal(订单)、Goods(货物)、Display(展示类)。

功能逻辑:

输入客户信息、货物列表、航班信息,校验航班载重能力。

货物计费逻辑:基于体积与重量的最大值计算计费重量,固定费率规则。

题目集2(扩展版):

新增特性:

货物分类:普通(Normal)、危险品(Dangerous)、加急(Expedite)。

客户类型:个人(Individual)与企业(Corporate),享受不同折扣。

支付方式:微信、支付宝、现金。

架构调整:

Goods类新增kindP(客户类型)和kindG(货物类型)属性。

Rate和Price类引入策略模式,动态计算费率与价格。

Display类增加支付方式字段,输出逻辑更复杂。

  1. 类图与模块交互
    通过类图可见:

核心模块:

数据实体:Air管理航班信息,Goods存储货物属性,Deal关联订单与客户。

策略接口:Rateget(费率计算)、Priceget(价格计算)实现业务规则解耦。

展示层:Display聚合所有数据,负责格式化输出。

  1. 复杂度分析(基于截图数据)
    题目集1复杂度(图2):

方法平均复杂度:2.1

最大深度:4

方法数/类:3.5
问题点:Goods.rateWeight()和Air.canHold()方法逻辑简单,但Display.display()因多数据聚合输出导致圈复杂度较高(值为5)。

题目集2复杂度(图3):

方法平均复杂度:3.8(↑80%)

最大深度:6(↑50%)

方法数/类:4.2(↑20%)
问题点:

Rate.rateGet()方法因多层switch-case分支,圈复杂度达8(图3中Max Complexity=8)。

Price.priceGet()需处理客户类型与货物类型组合,逻辑耦合度高。

  1. 关键代码解析
    题目集2的动态费率计算:

java
class Rate implements Rateget {
@Override
public double rateGet(Goods good) {
double weight = good.rateWeight();
switch (good.getKindG()) {
case "Normal":
if (weight < 20) return 35;
else if (weight < 50) return 30;
else if (weight < 100) return 25;
else return 15;
case "Dangerous":
// 危险品费率规则
case "Expedite":
// 加急货物费率规则
default:
throw new IllegalArgumentException("Invalid goods type");
}
}
}
通过策略模式将费率规则与货物类型解耦,符合开闭原则。

题目集2的价格折扣逻辑:

java
class Price implements Priceget {
@Override
public double priceGet(Goods good, double rate) {
double discount = 1;
switch (good.getKindP()) {
case "Individual": discount = 0.9; break;
case "Corporate": discount = 0.8; break;
}
return rate * discount * good.rateWeight();
}
}
优化方向:

折扣策略可进一步抽象为DiscountStrategy接口,支持动态扩展。

三、采坑心得

  1. 输入顺序与参数传递错误
    问题:在扩展版中,Main类输入kindP(客户类型)和kindG(货物类型)时,顺序与Goods构造函数参数不匹配,导致类型赋值错误。

解决:通过单元测试发现构造参数顺序应为kindP在前,调整输入代码:

java
Goods goods = new Goods(..., kindP, kindG); // 修正参数顺序
2. 接口设计冗余
问题:题目集1的Priceget接口仅支持priceGet(double, double),扩展版需传递Goods对象,导致接口方法爆炸(新增priceIGet())。

解决:重构接口为单一方法:

java
interface Priceget {
double calculatePrice(Goods good, double rate);
}
3. 数值精度丢失
问题:使用double存储电话号码(如13812345678)时,因浮点数精度丢失导致输出异常。

解决:将Client.phone和Deal.number改为String类型。

四、改进建议

使用策略模式解耦费率计算
问题:Rate.rateGet()方法包含多层分支,维护困难。

方案:为每类货物定义独立策略类:

java
interface RateStrategy {
double calculateRate(double weight);
}
class NormalRate implements RateStrategy {
public double calculateRate(double weight) { /* 普通费率逻辑 */ }
}
增强输入校验
问题:未校验支付方式输入合法性。

方案:在Main类中增加正则匹配:

java
if (!p.matches("Wechat|ALiPay|Cash")) {
throw new InputMismatchException("Invalid payment type: " + p);
}
模块化展示逻辑
问题:Display.display()方法过长(40+行),圈复杂度高。

方案:拆分为OrderHeaderPrinter、GoodsDetailPrinter等子模块。

五、总结

  1. 学习收获
    设计模式应用:通过策略模式、接口隔离原则,提升了代码扩展性。
    调试能力:通过单元测试与边界条件覆盖,显著减少运行时错误。
    代码质量意识:复杂度分析工具的使用帮助识别高风险代码。

结语
两次题目集的开发实践,我不仅巩固了Java编程基础,更深刻体会到系统设计的重要性。从基础版到扩展版的开发,像是搭积木变造房子。一开始简单明了,后来加入货物分类、折扣和支付方式,挑战倍增。踩过输入顺序颠倒、数值精度丢失的坑,也学会了用模块化设计让代码更灵活。

posted on 2025-05-23 12:51  UnKn0wN__XD  阅读(31)  评论(0)    收藏  举报

导航