第二次blog作业
前言
知识点总结
- 题目集8:主要涉及面向对象编程的基础概念,如类的定义、封装、继承和多态。在“航空货运管理系统”中,需要定义多个类,如Customer、Goods、Flight和Order,并通过类的组合来实现系统功能。还涉及到基本的输入输出操作,以及简单的条件判断和循环语句。
- 题目集9:在题目集8的基础上,进一步深化了面向对象编程的应用,引入了抽象类、接口和策略模式。通过抽象类Custome和Goods,实现了不同类型客户和货物的多态性。使用接口PaymentStrategy实现了不同支付方式的策略模式,提高了代码的可扩展性和可维护性。同时,还涉及到流处理和格式化输出的知识。
设计与分析
题目集8:
航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
OO第九周作业题目说明.pdf
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为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
源代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Customer {
private String id;
private String name;
private String phone;
private String address;
public Customer(String id, String name, String phone, String address) {
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
}
public String getName() { return name; }
public String getPhone() { return phone; }
}
class Goods {
private String id;
private String name;
private double width;
private double length;
private double height;
private double grossWeight;
public Goods(String id, String name, double width, double length, double height, double grossWeight) {
this.id = id;
this.name = name;
this.width = width;
this.length = length;
this.height = height;
this.grossWeight = grossWeight;
}
public double calculateVolumeWeight() {
return (length * width * height) / 6000.0;
}
public double getChargeWeight() {
return Math.max(grossWeight, calculateVolumeWeight());
}
public double determineRate() {
double cw = getChargeWeight();
if (cw < 20) return 35.0;
else if (cw < 50) return 30.0;
else if (cw < 100) return 25.0;
else return 15.0;
}
public double computeFreight() {
return getChargeWeight() * determineRate();
}
public String getName() { return name; }
}
class Flight {
private String number;
private String departure;
private String arrival;
private String date;
private double maxWeight;
public Flight(String number, String departure, String arrival, String date, double maxWeight) {
this.number = number;
this.departure = departure;
this.arrival = arrival;
this.date = date;
this.maxWeight = maxWeight;
}
public String getNumber() { return number; }
public double getMaxWeight() { return maxWeight; }
}
class 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;
private Flight flight;
private Customer customer;
private List
public Order(String orderId, String orderDate, String senderAddress, String senderName, String senderPhone,
String receiverAddress, String receiverName, String receiverPhone, Flight flight, Customer customer,
List<Goods> goodsList) {
this.orderId = orderId;
this.orderDate = orderDate;
this.senderAddress = senderAddress;
this.senderName = senderName;
this.senderPhone = senderPhone;
this.receiverAddress = receiverAddress;
this.receiverName = receiverName;
this.receiverPhone = receiverPhone;
this.flight = flight;
this.customer = customer;
this.goodsList = goodsList;
}
public double calculateTotalWeight() {
double total = 0;
for (Goods g : goodsList) {
total += g.getChargeWeight();
}
return total;
}
public boolean checkWeightLimit() {
double total = calculateTotalWeight();
if (total > flight.getMaxWeight()) {
System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.\n", flight.getNumber());
return false;
}
return true;
}
public void generateOrderReport() {
System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getName(), customer.getPhone());
System.out.println("-----------------------------------------");
System.out.printf("航班号:%s\n", flight.getNumber());
System.out.printf("订单号:%s\n", orderId);
System.out.printf("订单日期:%s\n", orderDate);
System.out.printf("发件人姓名:%s\n", senderName);
System.out.printf("发件人电话:%s\n", senderPhone);
System.out.printf("发件人地址:%s\n", senderAddress);
System.out.printf("收件人姓名:%s\n", receiverName);
System.out.printf("收件人电话:%s\n", receiverPhone);
System.out.printf("收件人地址:%s\n", receiverAddress);
double totalWeight = calculateTotalWeight();
System.out.printf("订单总重量(kg):%.1f\n", totalWeight);
double totalFreight = 0;
for (Goods g : goodsList) {
totalFreight += g.computeFreight();
}
System.out.printf("微信支付金额:%.1f\n\n", totalFreight);
System.out.println("货物明细如下:");
System.out.println("-----------------------------------------");
System.out.println("明细编号 货物名称 计费重量 计费费率 应交运费");
for (int i = 0; i < goodsList.size(); i++) {
Goods g = goodsList.get(i);
double cw = g.getChargeWeight();
double rate = g.determineRate();
double freight = g.computeFreight();
System.out.printf("%d %-10s %.1f %.1f %.1f\n", i + 1, g.getName(), cw, rate, freight);
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String customerId = scanner.nextLine().trim();
String customerName = scanner.nextLine().trim();
String customerPhone = scanner.nextLine().trim();
String customerAddress = scanner.nextLine().trim();
int goodsCount = Integer.parseInt(scanner.nextLine());
List<Goods> goodsList = new ArrayList<>();
for (int i = 0; i < goodsCount; i++) {
String goodsId = scanner.nextLine().trim();
String goodsName = scanner.nextLine().trim();
double width = Double.parseDouble(scanner.nextLine());
double length = Double.parseDouble(scanner.nextLine());
double height = Double.parseDouble(scanner.nextLine());
double grossWeight = Double.parseDouble(scanner.nextLine());
goodsList.add(new Goods(goodsId, goodsName, width, length, height, grossWeight));
}
String flightNumber = scanner.nextLine().trim();
String departure = scanner.nextLine().trim();
String arrival = scanner.nextLine().trim();
String flightDate = scanner.nextLine().trim();
double maxWeight = Double.parseDouble(scanner.nextLine());
Flight flight = new Flight(flightNumber, departure, arrival, flightDate, maxWeight);
String orderId = scanner.nextLine().trim();
String orderDate = scanner.nextLine().trim();
String senderAddress = scanner.nextLine().trim();
String senderName = scanner.nextLine().trim();
String senderPhone = scanner.nextLine().trim();
String receiverAddress = scanner.nextLine().trim();
String receiverName = scanner.nextLine().trim();
String receiverPhone = scanner.nextLine().trim();
Customer customer = new Customer(customerId, customerName, customerPhone, customerAddress);
Order order = new Order(orderId, orderDate, senderAddress, senderName, senderPhone,
receiverAddress, receiverName, receiverPhone, flight, customer, goodsList);
if (!order.checkWeightLimit()) {
return;
}
}
}
分析:

Main.java 文件包含 4 个类 / 接口,代码行数 205 行,语句数 118,注释比例为 0.0%(缺乏必要注释,可读性待提升)。最复杂方法为 Goods.determineRate(),其复杂度为 5(条件判断较多,逻辑集中),行数 47,块深度 3,反映该方法处理多分支费率计算时的高内聚性,但可维护性不足。类的方法数平均 4 个,每个方法平均语句数 6.13,整体结构较简洁,但核心逻辑方法(如 determineRate())需优化。
题目集9:
航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
OO第十二周作业题目说明.pdf
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户类型[可输入项: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位小数。
输入样例:
在这里给出一组输入。例如:
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
输出样例:
在这里给出相应的输出。例如:
客户:郭靖(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
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Scanner;
abstract class Customer {
protected String type;
protected String id;
protected String name;
protected String phone;
protected String address;
public Customer(String type, String id, String name, String phone, String address) {
this.type = type;
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
}
public abstract double getDiscountRate();
}
class IndividualCustomer extends Customer {
public IndividualCustomer(String id, String name, String phone, String address) {
super("Individual", id, name, phone, address);
}
@Override
public double getDiscountRate() {
return 0.9;
}
}
class CorporateCustomer extends Customer {
public CorporateCustomer(String id, String name, String phone, String address) {
super("Corporate", id, name, phone, address);
}
@Override
public double getDiscountRate() {
return 0.8;
}
}
abstract class Goods {
protected String id;
protected String name;
protected double width;
protected double length;
protected double height;
protected double actualWeight;
public Goods(String id, String name, double width, double length, double height, double actualWeight) {
this.id = id;
this.name = name;
this.width = width;
this.length = length;
this.height = height;
this.actualWeight = actualWeight;
}
public double calculateVolumeWeight() {
double volume = width * length * height;
return volume / 6000;
}
public double calculateChargeWeight() {
double volumeWeight = calculateVolumeWeight();
return Math.max(actualWeight, volumeWeight);
}
public abstract double calculateRate();
}
class NormalGoods extends Goods {
public NormalGoods(String id, String name, double width, double length, double height, double actualWeight) {
super(id, name, width, length, height, actualWeight);
}
@Override
public double calculateRate() {
double chargeWeight = calculateChargeWeight();
if (chargeWeight < 20) return 35;
else if (chargeWeight < 50) return 30;
else if (chargeWeight < 100) return 25;
else return 15;
}
}
class ExpediteGoods extends Goods {
public ExpediteGoods(String id, String name, double width, double length, double height, double actualWeight) {
super(id, name, width, length, height, actualWeight);
}
@Override
public double calculateRate() {
double chargeWeight = calculateChargeWeight();
if (chargeWeight < 20) return 60;
else if (chargeWeight < 50) return 50;
else if (chargeWeight < 100) return 40;
else return 30;
}
}
class DangerousGoods extends Goods {
public DangerousGoods(String id, String name, double width, double length, double height, double actualWeight) {
super(id, name, width, length, height, actualWeight);
}
@Override
public double calculateRate() {
double chargeWeight = calculateChargeWeight();
if (chargeWeight < 20) return 80;
else if (chargeWeight < 50) return 50;
else if (chargeWeight < 100) return 30;
else return 20;
}
}
interface PaymentStrategy {
String getPaymentType();
double pay(double amount);
}
class WechatPayment implements PaymentStrategy {
@Override
public String getPaymentType() {
return "微信";
}
@Override
public double pay(double amount) {
return amount; // 实际支付逻辑可扩展
}
}
class AlipayPayment implements PaymentStrategy {
@Override
public String getPaymentType() {
return "支付宝";
}
@Override
public double pay(double amount) {
return amount;
}
}
class CashPayment implements PaymentStrategy {
@Override
public String getPaymentType() {
return "现金";
}
@Override
public double pay(double amount) {
return amount;
}
}
class Flight {
private String flightNo;
private String departureAirport;
private String arrivalAirport;
private String date;
private double maxLoad;
public Flight(String flightNo, String departureAirport, String arrivalAirport, String date, double maxLoad) {
this.flightNo = flightNo;
this.departureAirport = departureAirport;
this.arrivalAirport = arrivalAirport;
this.date = date;
this.maxLoad = maxLoad;
}
public boolean isLoadAvailable(double totalWeight) {
return totalWeight <= maxLoad;
}
public String getFlightNo() { return flightNo; }
}
class Order {
private Customer customer;
private Flight flight;
private String orderId;
private String orderDate;
private String senderName;
private String senderPhone;
private String senderAddress;
private String receiverName;
private String receiverPhone;
private String receiverAddress;
private PaymentStrategy paymentStrategy;
private final ArrayList
private final DecimalFormat df = new DecimalFormat("0.0");
public Order(Customer customer, Flight flight, String orderId, String orderDate,
String senderName, String senderPhone, String senderAddress,
String receiverName, String receiverPhone, String receiverAddress,
PaymentStrategy paymentStrategy) {
this.customer = customer;
this.flight = flight;
this.orderId = orderId;
this.orderDate = orderDate;
this.senderName = senderName;
this.senderPhone = senderPhone;
this.senderAddress = senderAddress;
this.receiverName = receiverName;
this.receiverPhone = receiverPhone;
this.receiverAddress = receiverAddress;
this.paymentStrategy = paymentStrategy;
}
public void addGoods(Goods goods) {
goodsList.add(goods);
}
public double calculateTotalWeight() {
return goodsList.stream().mapToDouble(Goods::calculateChargeWeight).sum();
}
public void generateReport() {
double totalWeight = calculateTotalWeight();
if (!flight.isLoadAvailable(totalWeight)) {
System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.%n",
flight.getFlightNo());
return;
}
double totalFee = goodsList.stream()
.mapToDouble(g -> g.calculateChargeWeight() * g.calculateRate())
.sum();
double discount = customer.getDiscountRate();
double paymentAmount = totalFee * discount;
System.out.printf("客户:%s(%s)订单信息如下:%n", customer.name, customer.phone);
System.out.println("-----------------------------------------");
System.out.printf("航班号:%s%n", flight.getFlightNo());
System.out.printf("订单号:%s%n", orderId);
System.out.printf("订单日期:%s%n", orderDate);
System.out.printf("发件人姓名:%s%n", senderName);
System.out.printf("发件人电话:%s%n", senderPhone);
System.out.printf("发件人地址:%s%n", senderAddress);
System.out.printf("收件人姓名:%s%n", receiverName);
System.out.printf("收件人电话:%s%n", receiverPhone);
System.out.printf("收件人地址:%s%n", receiverAddress);
System.out.printf("订单总重量(kg):%s%n", df.format(totalWeight));
System.out.printf("%s支付金额:%s%n%n", paymentStrategy.getPaymentType(), df.format(paymentAmount));
System.out.println("货物明细如下:");
System.out.println("-----------------------------------------");
System.out.println("明细编号 货物名称 计费重量 计费费率 应交运费");
for (int i = 0; i < goodsList.size(); i++) {
Goods goods = goodsList.get(i);
double chargeWeight = goods.calculateChargeWeight();
double rate = goods.calculateRate();
double fee = chargeWeight * rate;
System.out.printf("%d %s %s %s %s%n",
i + 1, goods.name, df.format(chargeWeight), df.format(rate), df.format(fee));
}
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String customerType = sc.next();
String customerId = sc.next();
String customerName = sc.next();
String customerPhone = sc.next();
String customerAddress = sc.next();
Customer customer;
if ("Individual".equals(customerType)) {
customer = new IndividualCustomer(customerId, customerName, customerPhone, customerAddress);
} else {
customer = new CorporateCustomer(customerId, customerName, customerPhone, customerAddress);
}
String goodsType = sc.next();
int goodsCount = sc.nextInt();
ArrayList<Goods> goodsList = new ArrayList<>();
for (int i = 0; i < goodsCount; i++) {
String goodsId = sc.next();
String goodsName = sc.next();
double width = sc.nextDouble();
double length = sc.nextDouble();
double height = sc.nextDouble();
double actualWeight = sc.nextDouble();
Goods goods;
switch (goodsType) {
case "Normal":
goods = new NormalGoods(goodsId, goodsName, width, length, height, actualWeight);
break;
case "Expedite":
goods = new ExpediteGoods(goodsId, goodsName, width, length, height, actualWeight);
break;
case "Dangerous":
goods = new DangerousGoods(goodsId, goodsName, width, length, height, actualWeight);
break;
default:
throw new IllegalArgumentException("Invalid goods type");
}
goodsList.add(goods);
}
String flightNo = sc.next();
String departureAirport = sc.next();
String arrivalAirport = sc.next();
String flightDate = sc.next();
double maxLoad = sc.nextDouble();
Flight flight = new Flight(flightNo, departureAirport, arrivalAirport, flightDate, maxLoad);
String orderId = sc.next();
String orderDate = sc.next();
String senderAddress = sc.next();
String senderName = sc.next();
String senderPhone = sc.next();
String receiverAddress = sc.next();
String receiverName = sc.next();
String receiverPhone = sc.next();
String paymentType = sc.next();
PaymentStrategy paymentStrategy;
switch (paymentType) {
case "Wechat":
paymentStrategy = new WechatPayment();
break;
case "ALiPay":
paymentStrategy = new AlipayPayment();
break;
case "Cash":
paymentStrategy = new CashPayment();
break;
default:
throw new IllegalArgumentException("Invalid payment type");
}
Order order = new Order(customer, flight, orderId, orderDate,
senderName, senderPhone, senderAddress,
receiverName, receiverPhone, receiverAddress,
paymentStrategy);
goodsList.forEach(order::addGoods);
order.generateReport();
sc.close();
}
}
Main.java 文件包含 11 个类 / 接口,代码行数 351,语句数 178,注释比例仅 0.3%(需加强注释)。最复杂方法为 ExpediteGoods.calculateRate(),复杂度 5(处理加急货物费率的多条件判断),行数 81,块深度 6,反映逻辑密集性。类平均方法数 5.64,单个方法平均语句数 0.79(部分方法可优化)。
采坑心得
题目集8
- 输入格式问题:在读取输入时,由于使用Scanner类,需要注意输入的格式和顺序。如果输入格式不符合要求,可能会导致程序抛出异常或产生错误的结果。例如,在读取整数时,如果输入的不是有效的整数,会抛出NumberFormatException异常。
- 重量计算问题:在计算货物的计费重量时,需要考虑体积重量和实际重量的大小关系,取较大值作为计费重量。如果忽略了这一点,可能会导致运费计算错误。
题目集9
- 抽象类和接口的使用:在使用抽象类和接口时,需要正确理解它们的概念和用途。抽象类不能实例化,只能作为基类被继承,而接口是一种特殊的抽象类,只包含抽象方法。在实现抽象类和接口时,需要确保所有的抽象方法都被实现,否则会导致编译错误。
- 策略模式的应用:在使用策略模式时,需要正确设计和实现策略接口和具体策略类。在选择具体策略时,需要根据实际情况进行判断,避免出现逻辑错误。
改进建议
题目集8
- 代码复用:可以将一些重复的代码提取成方法,提高代码的复用性。例如,在Order类的generateOrderReport()方法中,有一些格式化输出的代码可以提取成一个单独的方法。
- 异常处理:在读取输入时,可以增加异常处理机制,提高程序的健壮性。例如,在读取整数时,可以使用try-catch块捕获NumberFormatException异常,并给出相应的提示信息。
题目集9
- 代码注释:增加代码注释,提高代码的可读性。特别是在使用抽象类、接口和策略模式的地方,需要详细解释代码的功能和设计意图。
- 单元测试:编写单元测试用例,对各个类和方法进行测试,确保代码的正确性和稳定性。可以使用JUnit等测试框架来进行单元测试。
总结
学习收获
- 通过本阶段两次题目集的练习,深入理解了面向对象编程的基本概念,如类的定义、封装、继承和多态。
- 学会了使用抽象类、接口和策略模式来提高代码的可扩展性和可维护性。
- 掌握了基本的输入输出操作和异常处理机制,提高了程序的健壮性。
进一步学习方向
- 深入学习设计模式,了解更多的设计模式及其应用场景,提高代码的设计水平。
- 学习数据库编程,将航空货运管理系统与数据库结合,实现数据的持久化存储和管理。
- 学习前端开发技术,开发一个可视化的用户界面,提高系统的用户体验。
对课程的建议
- 增加更多的实践案例和项目,让学生在实际项目中应用所学知识,提高解决实际问题的能力。
- 加强对设计模式和架构设计的教学,让学生了解如何设计出高质量的软件系统。
- 提供更多的学习资源和参考资料,帮助学生深入学习和研究相关知识。
浙公网安备 33010602011771号