第二次Blog作业

一.前言
这两次题目集主要考察的是类设计和完成类之间继承与多态的能力,虽然题目的量变大,但是难度对于我相较于第一次是变简单了,这也是我们不断学习并进步的过程吧。但遗憾的是我并没有取得满分。以下是我对这一次作业的总结:

  1. 首先,最明显的的就是迭代的数量由第一次的三次变为第二次的两次,也给我们减少了许多负担。
  2. 其次,这次题目变化为没有类图的形式,要求我们设计并总结的能力,这一点相对较为困难。
  3. 最后,这次难度是较为清晰明了的,但是工作量大为增加,也是巩固了一遍基础知识。
    二.设计与分析
    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 products;
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 设计与分析

  1. 基础信息模块
    Contact类
    良好地封装了地址、姓名、电话等通用信息,符合Information类的设计目标。
    Customer类
    继承逻辑通过组合Contact实现(而非直接继承),虽未严格继承但更灵活。
  2. 运输资源模块
    FlyingInfo类
    对应Flight类,完整管理航班信息(起降地址、时间、载重、航班号),字段命名清晰,功能完整。
  3. 货物处理模块
    ProductsControling类
    对Goods类,核心功能实现完整:
    正确计算体积重量(calculateVolumeWeight)。
    通过getChargeableWeight实现毛重逻辑(实际重量与体积重量取最大值)。
    运费费率分段计算逻辑合理(20/50/100kg分级)。
    类名拼写错误(应为ProductControlling或Goods),需修正。
  4. 业务逻辑模块
    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实现信息扩展),而多态则让我体会到接口抽象的灵活性(如不同类的统一方法调用)。在业务模块划分时,我认识到职责单一的重要性(如将货物、航班、订单逻辑分离),为后续开发打下坚实基础。

posted on 2025-05-25 23:24  春去也、  阅读(23)  评论(0)    收藏  举报

导航