航空货运管理系统
目录
前言
这两次题目围绕航空货运系统展开,实现了对输入数据的处理和输出,第一次的重点是类设计,第二次的重点是继承与多态。包含的类和属性比较多,但并不复杂。
设计与分析
类设计
题目说明
本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班
日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
客户信息(姓名,电话号码等)
货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期)
支付方式(支付宝支付、微信支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
计算规则
一、计费重量的确定
空运以实际重量(GrossWeight)和体积重量(VolumeWeight)中的较
高者作为计费重量。
计算公式:
体积重量(kg)= 货物体积(长×宽×高,单位:厘米)÷6000
示例:
若货物实际重量为80kg,体积为120cm×80cm×60cm,则:
体积重量 =(120×80×60)÷6000=96kg
计费重量取96kg(因96kg>80kg)。
二、基础运费计算
费率(Rate):航空公司或货代根据航线、货物类型、市场行情等制定(如
CNY 30/kg)。本次作业费率采用分段计算方式:
重量小于20,rate=35,重量大于等于20小于50,rate=30,重量大于等于50小于100,rate=25,重量大于等于100,rate=15
公式:基础运费 = 计费重量 × 费率
SourceMontor生成报表


我的类图

类设计分析
Customer类:封装客户基本信息
客户编号private String customerId
客户姓名private String name
客户电话private String phone
客户地址private String address
Cargo类:计算货物的体积重量和计费重量
货物编号private String cargoId
货物名称private String name
货物宽度private double width
货物长度private double length
货物高度private double height
货物重量private double weight
Flight类:管理航班载重容量
航班号private String flightNumber
航班起飞机场private String departureAirport
航班降落机场private String arrivalAirport
航班日期private String date
航班最大载重量private double maxCapacity
Order类:处理订单的创建和费用计算
订单编号private String orderId
订单日期private String orderDate
发件人地址private String senderAddress
发件人姓名private String senderName
发件人电话private String senderPhone
收件人地址private String receiverAddress
收件人姓名private String receiverName
收件人电话private String receiverPhone
Main类:负责用户输入和输出展示
继承与多态
题目说明
本题在类设计的基础上,对客户类型、运输方式进行分类处理,并且改变了支付金额的计算方法。
一、计费重量的确定
空运以实际重量(GrossWeight)和体积重量(VolumeWeight)中的较
高者作为计费重量。
计算公式:
体积重量(kg)= 货物体积(长×宽×高,单位:厘米)÷6000
示例:
若货物实际重量为80kg,体积为120cm×80cm×60cm,则:
体积重量 =(120×80×60)÷6000=96kg
计费重量取96kg(因96kg>80kg)。
二、基础运费计算
费率(Rate):航空公司或货代根据航线、货物类型、市场行情等制定(如
CNY30/kg)。本次作业费率与货物类型有关,货物类型分为普通货物、危险货
物和加急货物三种,其费率分别为:

计算公式:基础运费 = 计费重量 × 费率 × 折扣率
其中,折扣率是指不同的用户类型针对每个订单的运费可以享受相应的折扣,
在本题中,用户分为个人用户和集团用户,其中个人用户可享受订单运费的9
折优惠,集团用户可享受订单运费的8折优惠。
SourceMontor生成报表


我的类图

类设计分析
- Customer 抽象类
设计目的:作为客户类的抽象基类,统一管理客户的基本属性和行为,为不同类型客户(个人客户、企业客户)提供公共接口。
属性:包含 customerType(客户类型,如 “Individual”“Corporate” )、customerId(客户编号)、name(客户姓名)、phone(客户电话)、address(客户地址) 等属性,用于描述客户的基本信息。
方法:
getCustomerInfo() 抽象方法,用于获取客户的详细信息,由具体子类实现。
getDiscountRate() 抽象方法,用于获取客户对应的折扣率,不同子类根据客户类型实现不同折扣率逻辑。 - IndividualCustomer 类
设计目的:代表个人客户,继承自 Customer 抽象类,实现个人客户特有的行为和属性。
关系:继承自 Customer 类。
方法:
构造方法:接收客户编号、姓名、电话、地址,调用父类构造方法初始化相关属性。
重写 getCustomerInfo() 方法,返回个人客户的信息描述。
重写 getDiscountRate() 方法,返回个人客户的折扣率(0.9,即 9 折)。 - CorporateCustomer 类
设计目的:代表企业客户,继承自 Customer 抽象类,实现企业客户特有的行为和属性。
关系:继承自 Customer 类。
方法:
构造方法:接收客户编号、姓名、电话、地址,调用父类构造方法初始化相关属性。
重写 getCustomerInfo() 方法,返回企业客户的信息描述。
重写 getDiscountRate() 方法,返回企业客户的折扣率(0.8,即 8 折)。 - CargoType 抽象类
设计目的:作为货物类型的抽象基类,定义货物类型的通用属性和行为,为不同具体货物类型(普通货物、加急货物、危险货物)提供公共接口。
属性:包含 typeName(货物类型名称,如 “Normal”“Expedite”“Dangerous” )。
方法:
getTypeName() 方法,用于获取货物类型名称。
getRateByWeight(double weight) 抽象方法,根据货物重量获取对应的费率,由具体子类实现。
createCargoType(String typeName) 工厂方法,用于根据输入的货物类型名称创建对应的具体货物类型实例。 - NormalCargoType 类
设计目的:代表普通货物类型,继承自 CargoType 抽象类,实现普通货物类型特有的费率计算逻辑。
关系:继承自 CargoType 类。
方法:
构造方法:调用父类构造方法,传入 “Normal” 作为货物类型名称。
重写 getRateByWeight(double weight) 方法,根据普通货物的重量分段规则(如重量 < 20 时费率为 35 等)返回对应的费率。 - ExpediteCargoType 类
设计目的:代表加急货物类型,继承自 CargoType 抽象类,实现加急货物类型特有的费率计算逻辑。
关系:继承自 CargoType 类。
方法:
构造方法:调用父类构造方法,传入 “Expedite” 作为货物类型名称。
重写 getRateByWeight(double weight) 方法,根据加急货物的重量分段规则返回对应的费率。 - DangerousCargoType 类
设计目的:代表危险货物类型,继承自 CargoType 抽象类,实现危险货物类型特有的费率计算逻辑。
关系:继承自 CargoType 类。
方法:
构造方法:调用父类构造方法,传入 “Dangerous” 作为货物类型名称。
重写 getRateByWeight(double weight) 方法,根据危险货物的重量分段规则返回对应的费率。 - Goods 类
设计目的:代表具体的货物,实现 Cargo 接口,用于管理货物的详细信息和费用计算逻辑。
关系:实现 Cargo 接口。
属性:包含 goodsId(货物编号)、name(货物名称)、width(货物宽度)、length(货物长度)、height(货物高度)、weight(货物重量)、cargoType(货物类型,CargoType 类实例)。
方法:
构造方法:接收货物的各项信息,初始化相关属性。
实现 calculateFee() 方法,根据货物重量调用 CargoType 中获取费率的方法,并结合假设的折扣率(此处假设为 1,可按需完善)计算货物费用。
实现 getWeight()、getName()、getCargoType() 方法,用于获取货物的重量、名称和货物类型。 - Flight 类
设计目的:用于管理航班的相关信息和承载能力,处理订单与航班承载的关系。
属性:包含 flightNumber(航班号)、departureAirport(起飞机场)、arrivalAirport(降落机场)、date(航班日期)、maxWeight(航班最大载重量)、currentWeight(当前已承载重量)、orders(该航班承载的订单列表)。
方法:
构造方法:接收航班的各项信息,初始化相关属性。
canCarry(double weight) 方法,用于检查航班是否还能承载额外的重量。
addOrder(Order order) 方法,用于尝试将订单添加到航班,如果航班能承载则更新当前已承载重量并添加订单,返回操作结果。 - PaymentStrategy 接口
设计目的:作为支付策略的接口,定义支付方式的通用行为,为不同具体支付策略(微信支付、支付宝支付、现金支付)提供规范。
方法:
getPaymentMethodText() 方法,用于获取支付方式的文本描述(如 “微信”“支付宝”“现金” )。
generatePaymentInfo(double amount) 方法,用于根据支付金额生成支付信息。 - WechatPayment 类
设计目的:代表微信支付策略,实现 PaymentStrategy 接口,处理微信支付相关的行为。
关系:实现 PaymentStrategy 接口。
方法:
重写 getPaymentMethodText() 方法,返回 “微信”。
重写 generatePaymentInfo(double amount) 方法,生成微信支付的金额信息。 - AlipayPayment 类
设计目的:代表支付宝支付策略,实现 PaymentStrategy 接口,处理支付宝支付相关的行为。
关系:实现 PaymentStrategy 接口。
方法:
重写 getPaymentMethodText() 方法,返回 “支付宝”。
重写 generatePaymentInfo(double amount) 方法,生成支付宝支付的金额信息。 - CashPayment 类
设计目的:代表现金支付策略,实现 PaymentStrategy 接口,处理现金支付相关的行为。
关系:实现 PaymentStrategy 接口。
方法:
重写 getPaymentMethodText() 方法,返回 “现金”。
重写 generatePaymentInfo(double amount) 方法,生成现金支付的金额信息。 - PaymentFactory 类
设计目的:作为支付策略的工厂类,根据输入的支付类型创建对应的支付策略实例,实现解耦和代码复用。
方法:createPaymentStrategy(String paymentType) 工厂方法,根据支付类型(如 “Wechat”“ALiPay”“Cash” )创建并返回对应的支付策略实例。 - Order 类
设计目的:用于管理订单的相关信息和业务逻辑,包括订单基本信息、货物信息、支付信息等。
属性:包含 orderId(订单编号)、orderDate(订单日期)、senderAddress(发件人地址)、senderName(发件人姓名)、senderPhone(发件人电话)、receiverAddress(收件人地址)、receiverName(收件人姓名)、receiverPhone(收件人电话)、paymentStrategy(支付策略实例)、cargoList(订单包含的货物列表)、totalWeight(订单总重量)、totalFee(订单原始总费用,未应用折扣)、customer(客户实例)。
方法:
构造方法:接收订单的各项信息,初始化相关属性。
addCargo(Cargo cargo) 方法,用于向订单中添加货物,更新订单总重量和原始总费用。
getTotalFee() 方法,重写后应用客户的折扣率计算最终订单总费用。
getOriginalTotalFee() 方法,用于获取订单的原始总费用(未应用折扣),供输出显示明细时使用。
其他一系列 get 方法,用于获取订单的各项基本信息。
getPaymentMethodText() 方法,调用支付策略的对应方法获取支付方式文本描述。
getPaymentInfo() 方法,调用支付策略的对应方法生成支付信息。
踩坑心得
在IndividualCustomer 和CorporateCustomer 中重写getCustomerInfo 和getDiscountRate 方法时,没有保证方法签名(包括返回值类型、方法名、参数列表)完全一致,无法实现多态效果,导致编译错误。
在CargoType 子类中计算费率时条件判断范围写错,未考虑费率值,导致计算错误。当时没有看到那一串红色字体,没看到折扣,找了好久的错误。
在判断航班是否能承载订单时,Flight 类中canCarry 方法的逻辑依赖于当前已承载重量currentWeight 和订单重量的比较,未考虑到添加订单时更新currentWeight ,导致航班载重管理混乱,出现超载判断不准确的情况。
改进
减少类间耦合:
进一步解耦相关类。例如,在Order 类中,对于货物费用计算等逻辑,可通过引入更抽象的接口或服务类来处理,减少对Goods 类和CargoType 类内部细节的直接依赖,提高代码的可维护性和可测试性。
对于Flight 类和Order 类之间的关系,可以考虑引入中介者模式或观察者模式,使它们之间的交互更加清晰和可控,避免出现直接的强依赖。
重构重复代码:检查并提取各子类中重复的代码逻辑到父类或公共工具类中。例如,在NormalCargoType 、ExpediteCargoType 和DangerousCargoType 中,获取费率的逻辑结构相似,可考虑提取公共方法来简化代码,提高代码复用性。
丰富费用计算逻辑:
考虑更多影响运费的因素,如不同时间段的优惠、不同航线的附加费等。可以在Goods 类或相关费用计算类中增加相应属性和计算方法,使运费计算更加符合实际业务需求。
对于折扣率,可将其设计为可配置的,从配置文件或数据库中读取,方便业务人员根据实际情况灵活调整,而不是硬编码在代码中。
优化航班载重管理:
引入更智能的订单分配算法,当存在多个航班时,根据航班的剩余载重量、飞行计划、目的地等因素,合理分配订单,提高航班资源利用率,避免出现部分航班闲置而部分航班超载的情况。
记录航班载重的历史数据,便于进行数据分析和统计,为后续的航班规划和资源调配提供依据。
总结
写完blog后发现这两次题目也不是那么难,我当时为什么没写出来呢😅
浙公网安备 33010602011771号