第二次Blog作业
一.前言
这两次题目集主要考察的是类设计和完成类之间继承与多态的能力,虽然题目的量变大,但是难度对于我相较于第一次是变简单了,这也是我们不断学习并进步的过程吧。但遗憾的是我并没有取得满分。以下是我对这一次作业的总结:
- 首先,最明显的的就是迭代的数量由第一次的三次变为第二次的两次,也给我们减少了许多负担。
- 其次,这次题目变化为没有类图的形式,要求我们设计并总结的能力,这一点相对较为困难。
- 最后,这次难度是较为清晰明了的,但是工作量大为增加,也是巩固了一遍基础知识。
二.设计与分析
1. OPP-1 航空货运管理系统 1
1.1 题目
航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户编号
客户姓名
客户电话
客户地址
运送货物数量
货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
航班号
航班起飞机场
航班降落机场
航班日期(格式为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位小数。
输入样例:
在这里给出一组输入。例如:
10001
郭靖
13807911234
南昌航空大学
2
101
发电机
80
60
40
80
102
信号发生器
55
70
60
45
MU1234
昌北国际机场
大兴国际机场
2025-04-22
1000
900001
2025-04-22
南昌大学
洪七公
18907912325
北京大学
黄药师
13607912546
输出样例:
在这里给出相应的输出。例如:
客户:郭靖(13807911234)订单信息如下:
航班号:MU1234
订单号:900001
订单日期:2025-04-22
发件人姓名:洪七公
发件人电话:18907912325
发件人地址:南昌大学
收件人姓名:黄药师
收件人电话:13607912546
收件人地址:北京大学
订单总重量(kg):125.0
微信支付金额:3350.0
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 发电机 80.0 25.0 2000.0
2 信号发生器 45.0 30.0 1350.0
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
1.2 源码
`import java.util.Scanner;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
class Contact {
private String name;
private String phone;
private String address;
public Contact(String name, String phone, String address) {
this.name = name;
this.phone = phone;
this.address = address;
}
public String getName() { return name; }
public String getPhone() { return phone; }
public String getAddress() { return address; }
}
class Customer {
private int customerId;
private Contact contact;
public Customer(int customerId, String name, String phone, String address) {
this.customerId = customerId;
this.contact = new Contact(name, phone, address);
}
public int getCustomerId() { return customerId; }
public String getName() { return contact.getName(); }
public String getPhone() { return contact.getPhone(); }
public String getAddress() { return contact.getAddress(); }
}
class ProductsControling {
private int productId;
private String productName;
private double width;
private double length;
private double height;
private double weight;
public ProductsControling(int productId, String productName,
double width, double length,
double height, double weight) {
this.productId = productId;
this.productName = productName;
this.width = width;
this.length = length;
this.height = height;
this.weight = weight;
}
public double calculateVolumeWeight() {
return (length * width * height) / 6000;
}
public double getChargeableWeight() {
return Math.max(weight, calculateVolumeWeight());
}
public double calculateShippingFee() {
double chargeableWeight = getChargeableWeight();
double rate;
if (chargeableWeight < 20) {
rate = 35;
} else if (chargeableWeight < 50) {
rate = 30;
} else if (chargeableWeight < 100) {
rate = 25;
} else {
rate = 15;
}
return chargeableWeight * rate;
}
public int getProductId() { return productId; }
public String getProductName() { return productName; }
public double getWidth() { return width; }
public double getLength() { return length; }
public double getHeight() { return height; }
public double getWeight() { return weight; }
}
class FlyingInfo {
private String flightNumber;
private String departureAirport;
private String arrivalAirport;
private String flightDate;
private double maxLoadCapacity;
public FlyingInfo(String flightNumber, String departureAirport,
String arrivalAirport, String flightDate,
double maxLoadCapacity) {
this.flightNumber = flightNumber;
this.departureAirport = departureAirport;
this.arrivalAirport = arrivalAirport;
this.flightDate = flightDate;
this.maxLoadCapacity = maxLoadCapacity;
}
public String getFlightNumber() { return flightNumber; }
public String getDepartureAirport() { return departureAirport; }
public String getArrivalAirport() { return arrivalAirport; }
public String getFlightDate() { return flightDate; }
public double getMaxLoadCapacity() { return maxLoadCapacity; }
}
class OrderInfo {
private int orderId;
private String orderDate;
private Contact sender;
private Contact receiver;
private List
private FlyingInfo flightInfo;
public OrderInfo(int orderId, String orderDate,
String senderName, String senderPhone, String senderAddress,
String receiverName, String receiverPhone, String receiverAddress,
FlyingInfo flightInfo, List<ProductsControling> products) {
this.orderId = orderId;
this.orderDate = orderDate;
this.sender = new Contact(senderName, senderPhone, senderAddress);
this.receiver = new Contact(receiverName, receiverPhone, receiverAddress);
this.flightInfo = flightInfo;
this.products = products;
}
public double calculateTotalWeight() {
double total = 0;
for (ProductsControling product : products) {
total += product.getChargeableWeight();
}
return total;
}
public double calculateTotalPayment() {
double total = 0;
for (ProductsControling product : products) {
total += product.calculateShippingFee();
}
return total;
}
public boolean checkOverload() {
return calculateTotalWeight() > flightInfo.getMaxLoadCapacity();
}
public int getOrderId() { return orderId; }
public String getOrderDate() { return orderDate; }
public Contact getSender() { return sender; }
public Contact getReceiver() { return receiver; }
public List<ProductsControling> getProducts() { return products; }
public FlyingInfo getFlightInfo() { return flightInfo; }
}
class Main {
public static void Main(String[] args) {
Scanner scanner = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("#0.0");
int customerId = Integer.parseInt(scanner.nextLine());
String customerName = scanner.nextLine();
String customerPhone = scanner.nextLine();
String customerAddress = scanner.nextLine();
Customer customer = new Customer(customerId, customerName, customerPhone, customerAddress);
int productCount = Integer.parseInt(scanner.nextLine());
List<ProductsControling> products = new ArrayList<>();
for (int i = 0; i < productCount; i++) {
int productId = Integer.parseInt(scanner.nextLine());
String productName = scanner.nextLine();
double width = Double.parseDouble(scanner.nextLine());
double length = Double.parseDouble(scanner.nextLine());
double height = Double.parseDouble(scanner.nextLine());
double weight = Double.parseDouble(scanner.nextLine());
products.add(new ProductsControling(productId, productName, width, length, height, weight));
}
String flightNumber = scanner.nextLine();
String departureAirport = scanner.nextLine();
String arrivalAirport = scanner.nextLine();
String flightDate = scanner.nextLine();
double maxLoadCapacity = Double.parseDouble(scanner.nextLine());
FlyingInfo flightInfo = new FlyingInfo(flightNumber, departureAirport, arrivalAirport, flightDate, maxLoadCapacity);
int orderId = Integer.parseInt(scanner.nextLine());
String orderDate = scanner.nextLine();
String senderName = scanner.nextLine();
String senderPhone = scanner.nextLine();
String senderAddress = scanner.nextLine();
String receiverName = scanner.nextLine();
String receiverPhone = scanner.nextLine();
String receiverAddress = scanner.nextLine();
OrderInfo order = new OrderInfo(orderId, orderDate,
senderName, senderPhone, senderAddress,
receiverName, receiverPhone, receiverAddress,
flightInfo, products);
if (order.checkOverload()) {
System.out.printf("The flight with flight number: %s has exceeded its load capacity and cannot carry the order.%n",
flightInfo.getFlightNumber());
return;
}
System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getName(), customer.getPhone());
System.out.println("-----------------------------------------");
System.out.println("航班号:" + flightInfo.getFlightNumber());
System.out.println("订单号:" + order.getOrderId());
System.out.println("订单日期:" + order.getOrderDate());
System.out.println("发件人姓名:" + order.getSender().getName());
System.out.println("发件人电话:" + order.getSender().getPhone());
System.out.println("发件人地址:" + order.getSender().getAddress());
System.out.println("收件人姓名:" + order.getReceiver().getName());
System.out.println("收件人电话:" + order.getReceiver().getPhone());
System.out.println("收件人地址:" + order.getReceiver().getAddress());
System.out.println("订单总重量(kg):" + df.format(order.calculateTotalWeight()));
System.out.println("微信支付金额:" + df.format(order.calculateTotalPayment()));
System.out.println();
System.out.println("货物明细如下:");
System.out.println("-----------------------------------------");
System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
int index = 1;
for (ProductsControling product : products) {
double chargeableWeight = product.getChargeableWeight();
double rate;
if (chargeableWeight < 20) {
rate = 35;
} else if (chargeableWeight < 50) {
rate = 30;
} else if (chargeableWeight < 100) {
rate = 25;
} else {
rate = 15;
}
System.out.printf("%d\t%s\t%s\t%s\t%s\n",
index++,
product.getProductName(),
df.format(chargeableWeight),
df.format(rate),
df.format(product.calculateShippingFee()));
}
}
}`
1.3 类图

1.4 设计与分析
- 基础信息模块
Contact类
良好地封装了地址、姓名、电话等通用信息,符合Information类的设计目标。
Customer类
继承逻辑通过组合Contact实现(而非直接继承),虽未严格继承但更灵活。 - 运输资源模块
FlyingInfo类
对应Flight类,完整管理航班信息(起降地址、时间、载重、航班号),字段命名清晰,功能完整。 - 货物处理模块
ProductsControling类
对Goods类,核心功能实现完整:
正确计算体积重量(calculateVolumeWeight)。
通过getChargeableWeight实现毛重逻辑(实际重量与体积重量取最大值)。
运费费率分段计算逻辑合理(20/50/100kg分级)。
类名拼写错误(应为ProductControlling或Goods),需修正。 - 业务逻辑模块
OrderInfo类
对应Order类,整合全流程信息并实现关键逻辑:
校验航班载重(checkOverload方法)。
计算总重量和总费用(calculateTotalWeight/Payment)。
字段设计涵盖客户、收发件人、航班、货物代理,符合需求。
1.5 踩坑心得
没有提前设计好类图,导致类与类之间关系职能混乱重复。
没有准确的定义抽象类的职能,使代码更加冗杂多余。
没有找准题目的测试点,应该看清题目再作答。
1.6 改进建议
类名与拼写
修正ProductsControling为ProductControlling或Goods。
考虑将Customer更名为CustomerInformation以更贴近需求。
输入校验
添加对输入数据有效性(如非负数、合理日期格式)的校验。
扩展性
使用接口(如TransportResource)抽象航班/货车等运输资源,便于扩展
2 OPP-2 航空货运管理系统2
2.1** 题目**
客户类型[可输入项:Individual/Corporate]
客户编号
客户姓名
客户电话
客户地址
货物类型[可输入项:Normal/Expedite/Dangerous]
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
支付方式[可输入项:Wechat/ALiPay/Cash]
输出格式:
如果订单中货物重量超过航班剩余载重量,程序输出The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order. ,程序终止运行。
如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
[微信/支付宝/现金]支付金额:
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
注:输出中实型数均保留1位小数。
输入样例1:
在这里给出一组输入。例如:
Corporate
10001
郭靖
13807911234
南昌航空大学
Expedite
2
101
发电机
80
60
40
80
102
信号发生器
55
70
60
45
MU1234
昌北国际机场
大兴国际机场
2025-04-22
1000
900001
2025-04-22
南昌大学
洪七公
18907912325
北京大学
黄药师
13607912546
ALiPay
输出样例1:
在这里给出相应的输出。例如:
客户:郭靖(13807911234)订单信息如下:
航班号:MU1234
订单号:900001
订单日期:2025-04-22
发件人姓名:洪七公
发件人电话:18907912325
发件人地址:南昌大学
收件人姓名:黄药师
收件人电话:13607912546
收件人地址:北京大学
订单总重量(kg):125.0
支付宝支付金额:4360.0
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 发电机 80.0 40.0 3200.0
2 信号发生器 45.0 50.0 2250.0
代码长度限制
24 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
2.2 设计与分析
没通过。
2.3 踩坑心得
在这次作业中,我尝试引入策略模式优化支付逻辑,并新增客户类型折扣和货物类型费率功能,但最终代码混乱、耦合度高,未能达到预期效果。
支付模块设计失败
虽然用Payment抽象类实现了Wechat、AliPay等支付方式,但在Order类中错误地直接实例化支付对象,支付方式无法动态切换。
客户类型折扣逻辑混乱
在Agent类中硬编码了个人9折、企业8折的逻辑,但未考虑折扣叠加(,导致计算错误。更糟糕的是,我把折扣逻辑和运费计算耦合在一起,使得代码难以维护。
输入流程仍然脆弱
虽然调整了输入顺序,但未做数据校验(如客户类型是否合法、货物重量是否为正数),导致运行时频繁报错,调试困难。
我这次过度追求设计模式,却忽略了实际业务逻辑的合理性和代码的可维护性,最终导致系统难以扩展和调试。下次应先确保了解测试点,再逐步优化架构,完成题目。
2.4 改进建议
这次编程作业没做出来,确实暴露了我学习中的几个问题。首先是基础知识掌握不牢,各种技巧虽然教了但是下手时却使用苦难,还是应该多练习。
还有就是没把题目的要求理解透。看到题目说要加支付模块,就只顾着研究策略模式怎么实现,结果忽略了更基础的客户类型折扣和货物类型这些核心功能。写到一半发现逻辑混乱了,又回头改,徒增工作量。
这次失败让我明白,编程不能光记概念,得多动手实践。下次一定要先完全理解需求,把核心流程梳理清楚,再考虑设计模式这些高级技巧。基础打牢了,复杂的架构自然就能水到渠成。
3. 总结
通过这两次代码作业,我逐步掌握了面向对象编程的核心思想。在类与对象的设计中,我学会了如何用封装将数据与操作绑定,通过私有属性和公有方法确保数据安全(如Contact类隐藏细节,仅暴露接口)。继承的应用让我理解代码复用与层次化设计(如Customer组合Contact实现信息扩展),而多态则让我体会到接口抽象的灵活性(如不同类的统一方法调用)。在业务模块划分时,我认识到职责单一的重要性(如将货物、航班、订单逻辑分离),为后续开发打下坚实基础。
浙公网安备 33010602011771号