“航空货运管理系统”第二次Blog作业

一、前言


面向对象程序设计这门课上了大半个学期了,虽然领悟了面向对象的核心技术和及其独特的优势,但是我的代码结构仍然无法做到真正符合面向对象七大原则,让我意识到成为一名合格的程序员任重而道远,借这次Blog机会,结合我写的“航空货运管理系统”代码,我应该系统分析我存在的问题,后续应该积极改进。

两次航空货运管理系统设计的知识点有:
面向对象编程知识:如类设计、封装性、通过getter和setter方法实现数据交互、单一职责原则(SRP)、开闭原则(LSP)、依赖倒置原则(DIP)、迪米特法则(LOD)、合成复用原则(CRP);集合ArrayList知识的运用;输入输出处理;算法设计(如业务逻辑计算)等。

题量不大,难度中等偏上,对于业务逻辑的准确性(如计费规则边界处理)和数据交互的准确实现有一定难度,但是核心挑战在于类设计,使得代码符合面向对象七大原则,这需要我真正掌握面向对象知识并且能熟练运用。


二、设计与分析


8-3 NCHU_航空货运管理系统(类设计)


1.题目概述

本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班
日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
客户信息(姓名,电话号码等)
货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期)
支付方式(支付宝支付、微信支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信
息报表及货物明细报表。

本次作业主要考虑货物重量/体积,以下是计算方式的关键要点:

计费重量的确定:
空运以实际重量(GrossWeight)和体积重量(VolumeWeight)中的较高者作为计费重量。

计算公式:
体积重量(kg)= 货物体积(长×宽×高,单位:厘米)÷6000

示例:
若货物实际重量为80kg,体积为120cm×80cm×60cm,则:
体积重量 =(120×80×60)÷6000=96kg
计费重量取96kg(因96kg>80kg)。

基础运费计算

费率(Rate):
航空公司或货代根据航线、货物类型、市场行情等制定(如CNY 30/kg)。

本次作业费率采用分段计算方式:
公式:基础运费 = 计费重量 × 费率

输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话

输出格式:
如果订单中货物重量超过航班剩余载重量,程序输出The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order. ,程序终止运行。
如果航班载重量可以承接该订单,输出如下:

客户:姓名(电话)订单信息如下:

航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:

输入样例:
在这里给出一组输入。例如:

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

————————————————————————————————————————————————————————————————


**2.类图设计**

使用Powerdesigner给出的类图如下:


3.代码展示

点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Client {
    private String ID;
    private String name;
    private String phoneNumber;
    private String address;
    private int goodsNumber;

    public Client() {
    }

    public Client(String ID, String name, String phoneNumber, String address, int goodsNumber) {
        this.ID = ID;
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.address = address;
        this.goodsNumber = goodsNumber;
    }

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getGoodsNumber() {
        return goodsNumber;
    }

    public void setGoodsNumber(int goodsNumber) {
        this.goodsNumber = goodsNumber;
    }
}

class Goods {
    private String ID;
    private String name;
    private double width;
    private double length;
    private double height;
    private double weight;

    public Goods() {
    }

    public Goods(String ID, String name, double width, double length, double height, double weight) {
        this.ID = ID;
        this.name = name;
        this.width = width;
        this.length = length;
        this.height = height;
        this.weight = weight;
    }

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}

class Plane {
    private String ID;
    private String departure;
    private String arrival;
    private String date;
    private double maxWeight;

    public Plane() {
    }

    public Plane(String ID, String departure, String arrival, String date, double maxWeight) {
        this.ID = ID;
        this.departure = departure;
        this.arrival = arrival;
        this.date = date;
        this.maxWeight = maxWeight;
    }

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public String getDeparture() {
        return departure;
    }

    public void setDeparture(String departure) {
        this.departure = departure;
    }

    public String getArrival() {
        return arrival;
    }

    public void setArrival(String arrival) {
        this.arrival = arrival;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public double getMaxWeight() {
        return maxWeight;
    }

    public void setMaxWeight(double maxWeight) {
        this.maxWeight = maxWeight;
    }
}

class Order {
    private String ID;
    private String date;
    private String senderAddress;
    private String senderName;
    private String senderPhone;
    private String receiverAddress;
    private String receiverName;
    private String receiverPhone;

    public Order() {
    }

    public Order(String ID, String date, String senderAddress, String senderName, String senderPhone, String receiverAddress, String receiverName, String receiverPhone) {
        this.ID = ID;
        this.date = date;
        this.senderAddress = senderAddress;
        this.senderName = senderName;
        this.senderPhone = senderPhone;
        this.receiverAddress = receiverAddress;
        this.receiverName = receiverName;
        this.receiverPhone = receiverPhone;
    }

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getSenderAddress() {
        return senderAddress;
    }

    public void setSenderAddress(String senderAddress) {
        this.senderAddress = senderAddress;
    }

    public String getSenderName() {
        return senderName;
    }

    public void setSenderName(String senderName) {
        this.senderName = senderName;
    }

    public String getSenderPhone() {
        return senderPhone;
    }

    public void setSenderPhone(String senderPhone) {
        this.senderPhone = senderPhone;
    }

    public String getReceiverAddress() {
        return receiverAddress;
    }

    public void setReceiverAddress(String receiverAddress) {
        this.receiverAddress = receiverAddress;
    }

    public String getReceiverName() {
        return receiverName;
    }

    public void setReceiverName(String receiverName) {
        this.receiverName = receiverName;
    }

    public String getReceiverPhone() {
        return receiverPhone;
    }

    public void setReceiverPhone(String receiverPhone) {
        this.receiverPhone = receiverPhone;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取客户信息
        String clientID = scanner.nextLine();
        String clientName = scanner.nextLine();
        String clientPhone = scanner.nextLine();
        String clientAddress = scanner.nextLine();
        int goodsNumber = Integer.parseInt(scanner.nextLine());

        List<Goods> goodsList = new ArrayList<>();
        for (int i = 0; i < goodsNumber; i++) {
            String goodsID = scanner.nextLine();
            String goodsName = 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());

            Goods goods = new Goods(goodsID, goodsName, width, length, height, weight);
            goodsList.add(goods);
        }

        // 读取航班信息
        String flightID = scanner.nextLine();
        String departure = scanner.nextLine();
        String arrival = scanner.nextLine();
        String flightDate = scanner.nextLine();
        double maxWeight = Double.parseDouble(scanner.nextLine());

        // 读取订单信息
        String orderID = scanner.nextLine();
        String orderDate = scanner.nextLine();
        String senderAddress = scanner.nextLine();
        String senderName = scanner.nextLine();
        String senderPhone = scanner.nextLine();
        String receiverAddress = scanner.nextLine();
        String receiverName = scanner.nextLine();
        String receiverPhone = scanner.nextLine();

        // 计算每个货物的计费重量和总重量
        double totalWeight = 0.0;
        List<Double> chargeWeights = new ArrayList<>();
        for (Goods goods : goodsList) {
            double volumeWeight = (goods.getLength() * goods.getWidth() * goods.getHeight()) / 6000;
            double chargeWeight = Math.max(volumeWeight, goods.getWeight());
            chargeWeights.add(chargeWeight);
            totalWeight += chargeWeight;
        }

        // 判断航班载重量
        if (totalWeight > maxWeight) {
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.\n", flightID);
            return;
        }

        // 输出客户订单信息
        System.out.println("客户:" + clientName + "(" + clientPhone + ")订单信息如下:");
        System.out.println("-----------------------------------------");
        System.out.println("航班号:" + flightID);
        System.out.println("订单号:" + orderID);
        System.out.println("订单日期:" + orderDate);
        System.out.println("发件人姓名:" + senderName);
        System.out.println("发件人电话:" + senderPhone);
        System.out.println("发件人地址:" + senderAddress);
        System.out.println("收件人姓名:" + receiverName);
        System.out.println("收件人电话:" + receiverPhone);
        System.out.println("收件人地址:" + receiverAddress);
        System.out.printf("订单总重量(kg):%.1f\n", totalWeight);

        // 计算每个货物的费率和应交运费,以及总支付金额
        double totalPayment = 0.0;
        List<Double> rates = new ArrayList<>();
        List<Double> payments = new ArrayList<>();
        for (int i = 0; i < chargeWeights.size(); i++) {
            double chargeWeight = chargeWeights.get(i);
            double rate;
            if (chargeWeight < 20) {
                rate = 35;
            } else if (chargeWeight < 50) {
                rate = 30;
            } else if (chargeWeight < 100) {
                rate = 25;
            } else {
                rate = 15;
            }
            rates.add(rate);
            double payment = chargeWeight * rate;
            payments.add(payment);
            totalPayment += payment;
        }
        System.out.printf("微信支付金额:%.1f\n", totalPayment);
        System.out.printf("\n");

        // 输出货物明细
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for (int i = 0; i < goodsList.size(); i++) {
            Goods goods = goodsList.get(i);
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i + 1, goods.getName(), chargeWeights.get(i), rates.get(i), payments.get(i));
        }
    }
}





4.代码分析

(1)利用SourceMontor生成报表结果如下:


(2)类图分析:

结构复杂度:
分支百分比(% Branches):1.4% ,意味着代码中条件分支(如 if - else、switch 等)占比较小,代码执行路径相对简单直接,逻辑复杂度低。
调用次数(Calls):47 次,即代码中函数或方法调用的频率,较多调用说明代码有一定模块化,通过调用不同功能模块实现整体功能。

注释情况:
注释百分比(% Comments):1.5% ,注释比例较低。

类与方法相关:
类数量(Classes):5 个,代码采用了一定的面向对象设计,将功能封装在不同类中,但数量不算多。
每个类的方法数(Methods/Class):平均 11.40 个,说明类的职责可能不够单一,方法过多可能导致类功能混杂,违反高内聚原则,影响代码的可维护性和扩展性。
平均每个方法的语句数(Avg Stmts/Method):1.91 条,方法内语句较少,说明方法粒度较细,功能相对单一,符合代码设计中方法短小精悍的原则,便于理解和测试。

复杂度指标:
最大复杂度(Max Complexity):3 ,表明代码中最复杂方法在可接受范围。
最大深度(Max Depth):3 ,代表代码中嵌套结构(如循环、条件语句嵌套)的最大层数,层数不高,代码结构相对扁平,可读性较好。
平均深度(Avg Depth):1.55 ,说明整体代码嵌套深度较浅,逻辑结构简单。
平均复杂度(Avg Complexity):1.04 ,表明代码整体较容易理解和维护。

优点:
类职责基本清晰,实体属性封装合理,符合面向对象设计原则。
业务逻辑分层明确:输入读取→数据计算→结果输出流程清晰。

不足:
Main类臃肿:承担输入、计算、输出多重职责,违反单一职责原则,可维护性差。
缺乏输入验证:未对 ID 格式、电话号码有效性、重量 / 尺寸合法性进行校验,可能导致程序异常。
硬编码问题:费率规则(如 35、30 等数值)直接写入代码,后期修改成本高。


(3)改进建议:

  1. 重构代码结构,分离业务逻辑
    问题:Main类承担过多职责,逻辑混杂。

  2. 添加输入验证与异常处理
    问题:未处理非法输入,程序健壮性差。
    方案:
    对客户 ID、电话号码等字段添加格式校验(如电话号码匹配正则表达式)。
    使用try-catch块包裹输入代码,捕获NumberFormatException并提示用户重新输入。

  3. 优化类设计,提升内聚性
    问题:Order类包含发件人和收件人重复信息(地址、姓名、电话),可进一步封装。
    方案:创建ContactInfo类,包含姓名、电话、地址,Order类中使用该类实例:


(4)踩坑心得:
代码结构应该更深层次地考虑到单一职责原则,重视面向对象程序设计原则,改掉硬编码的思维模式,养成写注释的习惯


9-3 NCHU_航空货运管理系统(继承与多态)


**1.题目概述**

题目与“8-3 NCHU_航空货运管理系统”新增如下内容:

(1)对于不同货物类型,有了不同的计算费率公式:

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

(3)可以使用多种方式支付:

支付方式(支付宝支付、微信支付、现金支付)


输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。

客户类型[可输入项: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


2.类图设计

使用Powerdesigner给出的类图如下:


3.代码展示

点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 用户类,处理客户信息及折扣率
class User {
    private String clientType; // 客户类型:Individual/Corporate
    private String clientID;
    private String clientName;
    private String clientPhone;
    private String clientAddress;

    public User(String clientType, String clientID, String clientName, String clientPhone, String clientAddress) {
        this.clientType = clientType;
        this.clientID = clientID;
        this.clientName = clientName;
        this.clientPhone = clientPhone;
        this.clientAddress = clientAddress;
    }

    // 获取折扣率
    public double getDiscountRate() {
        if ("Individual".equals(clientType)) {
            return 0.9;
        } else {
            return 0.8;
        }
    }

    public String getClientName() {
        return clientName;
    }

    public String getClientPhone() {
        return clientPhone;
    }

    public String getClientType() {
        return clientType;
    }

    public void setClientType(String clientType) {
        this.clientType = clientType;
    }

    public String getClientID() {
        return clientID;
    }

    public void setClientID(String clientID) {
        this.clientID = clientID;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public void setClientPhone(String clientPhone) {
        this.clientPhone = clientPhone;
    }

    public String getClientAddress() {
        return clientAddress;
    }

    public void setClientAddress(String clientAddress) {
        this.clientAddress = clientAddress;
    }
}

// 货物类型枚举,定义不同类型的费率
enum GoodsType {
    Normal, Expedite, Dangerous
}

// 货物类,处理货物相关计算
class Goods {
    private String goodsID;
    private String goodsName;
    private double width;
    private double length;
    private double height;
    private double actualWeight;
    private GoodsType goodsType;

    public Goods(String goodsID, String goodsName, double width, double length, double height, double actualWeight, GoodsType goodsType) {
        this.goodsID = goodsID;
        this.goodsName = goodsName;
        this.width = width;
        this.length = length;
        this.height = height;
        this.actualWeight = actualWeight;
        this.goodsType = goodsType;
    }

    public String getGoodsID() {
        return goodsID;
    }

    public void setGoodsID(String goodsID) {
        this.goodsID = goodsID;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getActualWeight() {
        return actualWeight;
    }

    public void setActualWeight(double actualWeight) {
        this.actualWeight = actualWeight;
    }

    public GoodsType getGoodsType() {
        return goodsType;
    }

    public void setGoodsType(GoodsType goodsType) {
        this.goodsType = goodsType;
    }

    // 计算体积重量
    private double calculateVolumeWeight() {
        return (length * width * height) / 6000.0;
    }

    // 获取计费重量
    public double getChargeWeight() {
        return Math.max(actualWeight, calculateVolumeWeight());
    }

    // 获取货物费率
    public double getRate() {
        double chargeWeight = getChargeWeight();
        switch (goodsType) {
            case Normal:
                if (chargeWeight < 20) return 35;
                else if (chargeWeight < 50) return 30;
                else if (chargeWeight < 100) return 25;
                else return 15;
            case Dangerous:
                if (chargeWeight < 20) return 80;
                else if (chargeWeight < 50) return 50;
                else if (chargeWeight < 100) return 30;
                else return 20;
            case Expedite:
                if (chargeWeight < 20) return 60;
                else if (chargeWeight < 50) return 50;
                else if (chargeWeight < 100) return 40;
                else return 30;
            default:
                return 0; // 题目保证类型合法,实际不会执行到这里
        }
    }

    public String getGoodsName() {
        return goodsName;
    }
}

// 航班类,处理航班信息
class Plane {
    private String flightID;
    private String departureAirport;
    private String arrivalAirport;
    private String flightDate;
    private double maxLoadWeight;

    public Plane(String flightID, String departureAirport, String arrivalAirport, String flightDate, double maxLoadWeight) {
        this.flightID = flightID;
        this.departureAirport = departureAirport;
        this.arrivalAirport = arrivalAirport;
        this.flightDate = flightDate;
        this.maxLoadWeight = maxLoadWeight;
    }

    public void setFlightID(String flightID) {
        this.flightID = flightID;
    }

    public String getDepartureAirport() {
        return departureAirport;
    }

    public void setDepartureAirport(String departureAirport) {
        this.departureAirport = departureAirport;
    }

    public String getArrivalAirport() {
        return arrivalAirport;
    }

    public void setArrivalAirport(String arrivalAirport) {
        this.arrivalAirport = arrivalAirport;
    }

    public String getFlightDate() {
        return flightDate;
    }

    public void setFlightDate(String flightDate) {
        this.flightDate = flightDate;
    }

    public void setMaxLoadWeight(double maxLoadWeight) {
        this.maxLoadWeight = maxLoadWeight;
    }

    public double getMaxLoadWeight() {
        return maxLoadWeight;
    }

    public String getFlightID() {
        return flightID;
    }
}

// 订单类,处理订单信息及计算
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 User user;
    private Plane plane;
    private List<Goods> goodsList;
    private String paymentMethod;

    public Order(String orderID, String orderDate, String senderAddress, String senderName, String senderPhone,
                 String receiverAddress, String receiverName, String receiverPhone,
                 User user, Plane plane, List<Goods> goodsList, String paymentMethod) {
        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.user = user;
        this.plane = plane;
        this.goodsList = goodsList;
        this.paymentMethod = paymentMethod;
    }

    public String getOrderID() {
        return orderID;
    }

    public void setOrderID(String orderID) {
        this.orderID = orderID;
    }

    public String getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(String orderDate) {
        this.orderDate = orderDate;
    }

    public String getSenderAddress() {
        return senderAddress;
    }

    public void setSenderAddress(String senderAddress) {
        this.senderAddress = senderAddress;
    }

    public String getSenderName() {
        return senderName;
    }

    public void setSenderName(String senderName) {
        this.senderName = senderName;
    }

    public String getSenderPhone() {
        return senderPhone;
    }

    public void setSenderPhone(String senderPhone) {
        this.senderPhone = senderPhone;
    }

    public String getReceiverAddress() {
        return receiverAddress;
    }

    public void setReceiverAddress(String receiverAddress) {
        this.receiverAddress = receiverAddress;
    }

    public String getReceiverName() {
        return receiverName;
    }

    public void setReceiverName(String receiverName) {
        this.receiverName = receiverName;
    }

    public String getReceiverPhone() {
        return receiverPhone;
    }

    public void setReceiverPhone(String receiverPhone) {
        this.receiverPhone = receiverPhone;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Plane getPlane() {
        return plane;
    }

    public void setPlane(Plane plane) {
        this.plane = plane;
    }

    public List<Goods> getGoodsList() {
        return goodsList;
    }

    public void setGoodsList(List<Goods> goodsList) {
        this.goodsList = goodsList;
    }

    public String getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(String paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    // 计算订单总重量
    public double calculateTotalWeight() {
        double totalWeight = 0.0;

        for (int i = 0; i < goodsList.size(); i++) {
            Goods currentGoods = goodsList.get(i);
            double currentWeight = currentGoods.getChargeWeight();
            totalWeight = totalWeight + currentWeight;
        }

        return totalWeight;
    }

    // 计算总支付金额
    public double calculateTotalPayment() {
        double totalAmount = 0.0;
        double discountRate = user.getDiscountRate();

        // 使用索引遍历商品列表
        for (int i = 0; i < goodsList.size(); i++) {
            Goods item = goodsList.get(i);

            // 获取商品的计费重量和单价
            double weight = item.getChargeWeight();
            double pricePerUnit = item.getRate();

            // 计算单个商品的折扣后金额并累加到总金额
            double itemTotal = weight * pricePerUnit;  // 商品原价
            double discountedItemTotal = itemTotal * discountRate;  // 应用折扣
            totalAmount += discountedItemTotal;
        }

        return totalAmount;
    }

    // 获取支付方式显示名称
    public String getDisplayPaymentMethod() {
        switch (paymentMethod) {
            case "Wechat":
                return "微信";
            case "ALiPay":
                return "支付宝";
            case "Cash":
                return "现金";
            default:
                return paymentMethod; // 题目保证输入合法,无需处理默认情况
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取客户信息
        String clientType = scanner.nextLine();
        String clientID = scanner.nextLine();
        String clientName = scanner.nextLine();
        String clientPhone = scanner.nextLine();
        String clientAddress = scanner.nextLine();

        // 创建用户对象
        User user = new User(clientType, clientID, clientName, clientPhone, clientAddress);

        // 读取货物信息
        String goodsTypeStr = scanner.nextLine();
        GoodsType goodsType = GoodsType.valueOf(goodsTypeStr);
        int goodsNumber = Integer.parseInt(scanner.nextLine());

        List<Goods> goodsList = new ArrayList<>();
        for (int i = 0; i < goodsNumber; i++) {
            String goodsID = scanner.nextLine();
            String goodsName = scanner.nextLine();
            double width = Double.parseDouble(scanner.nextLine());
            double length = Double.parseDouble(scanner.nextLine());
            double height = Double.parseDouble(scanner.nextLine());
            double actualWeight = Double.parseDouble(scanner.nextLine());

            Goods goods = new Goods(goodsID, goodsName, width, length, height, actualWeight, goodsType);
            goodsList.add(goods);
        }

        // 读取航班信息
        String flightID = scanner.nextLine();
        String departure = scanner.nextLine();
        String arrival = scanner.nextLine();
        String flightDate = scanner.nextLine();
        double maxWeight = Double.parseDouble(scanner.nextLine());

        Plane plane = new Plane(flightID, departure, arrival, flightDate, maxWeight);

        // 读取订单信息
        String orderID = scanner.nextLine();
        String orderDate = scanner.nextLine();
        String senderAddress = scanner.nextLine();
        String senderName = scanner.nextLine();
        String senderPhone = scanner.nextLine();
        String receiverAddress = scanner.nextLine();
        String receiverName = scanner.nextLine();
        String receiverPhone = scanner.nextLine();
        String paymentMethod = scanner.nextLine();

        Order order = new Order(orderID, orderDate, senderAddress, senderName, senderPhone,
                receiverAddress, receiverName, receiverPhone, user, plane, goodsList, paymentMethod);

        // 计算总重量并检查航班载重
        double totalWeight = order.calculateTotalWeight();
        if (totalWeight > plane.getMaxLoadWeight()) {
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.\n", flightID);
            return;
        }

        // 输出订单信息
        System.out.println("客户:" + user.getClientName() + "(" + user.getClientPhone() + ")订单信息如下:");
        System.out.println("-----------------------------------------");
        System.out.println("航班号:" + flightID);
        System.out.println("订单号:" + orderID);
        System.out.println("订单日期:" + orderDate);
        System.out.println("发件人姓名:" + senderName);
        System.out.println("发件人电话:" + senderPhone);
        System.out.println("发件人地址:" + senderAddress);
        System.out.println("收件人姓名:" + receiverName);
        System.out.println("收件人电话:" + receiverPhone);
        System.out.println("收件人地址:" + receiverAddress);
        System.out.printf("订单总重量(kg):%.1f\n", totalWeight);
        System.out.printf("%s支付金额:%.1f\n", order.getDisplayPaymentMethod(), order.calculateTotalPayment());
        System.out.println();

        // 输出货物明细
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for (int i = 0; i < goodsList.size(); i++) {
            Goods goods = goodsList.get(i);
            double chargeWeight = goods.getChargeWeight();
            double rate = goods.getRate();
            double payment = chargeWeight * rate;
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i + 1, goods.getGoodsName(), chargeWeight, rate, payment);
        }

        scanner.close();
    }
}



**4.代码分析**

(1)利用SourceMontor生成报表结果如下:

(2)类图分析:

结构相关
% Branches:10.7 ,分支(如 if - else、switch 等分支结构)占比 10.7% ,说明代码中分支逻辑不算特别多。
Calls:21 ,方法调用次数为 21 次。
% Comments:3.6 ,注释占比仅 3.6% ,注释过少。

类与方法相关
Methods/Class:16.50 ,平均每个类包含 16.5 个方法,类的职责可能不够单一,存在功能过于聚合的可能。
Avg Stmts/Method:3.59 ,平均每个方法的语句数为 3.59 条,方法体相对较简洁。

复杂度相关
Max Complexity:14 ,代码中方法的最大复杂度为 14 ,存在部分较复杂难维护的方法。
Max Depth:4 ,代码的最大深度为 4 ,反映代码嵌套层次情况。
Avg Depth:1.33 ,平均深度 1.33 ,整体嵌套情况不算严重。
Avg Complexity:1.43 ,平均复杂度 1.43 ,表明整体代码复杂度不算高。

优点:
代码结构清晰,完整实现了航空货运的核心业务流程。

缺点分析:
增加输入校验(如非空检查、数值范围校验)和异常处理,避免程序崩溃。

将硬编码的常量(如6000、折扣率、费率)提取为类常量。

提升可扩展性。

将Order类的计算与输出逻辑分离,遵循单一职责原则。


(3)改进建议:

  1. 设计模式优化
    现状:User.getDiscountRate()通过if-else判断客户类型,新增客户类型需修改代码。
    改进:
    定义DiscountStrategy接口;实现具体策略(个人、企业);User类依赖策略接口,而非硬编码;

  2. 代码健壮性增强
    输入校验:
    增加客户电话号码格式校验(正则表达式)。
    货物尺寸和重量需限制最小值(如width > 0)。
    异常处理:
    使用try-catch包裹Scanner输入,处理NumberFormatException。
    在Order类中增加空指针校验(如goodsList != null)。

  3. 可维护性改进
    注释补充:
    在Goods.getRate()中添加费率表说明。


(4)踩坑心得:

面向接口编程是企业中普遍运用的模式,而我缺乏相关思维模式,应该增强面向对象设计原则知识的学习和运用,多运用继承与多态来解决实际问题


三、总结

(1)我学到了什么:

我的面向对象编程(OOP)核心能力得到提升,类与对象设计、继承与多态等知识的运用;
集合框架ArrayList知识点学习和使用;
输入输出处理;
编程规范与调试能力。

(2)进一步学习的方向:
代码健壮性与异常处理;
代码复用性:部分重复逻辑(如循环遍历集合)可提取为工具方法
多态应用:当前货物费率通过switch实现,定义RateStrategy接口,不同货物类型实现具体计算逻辑,提升扩展性
面向接口编程模式的学习;
泛型深入:学习使用通配符(?)、上限 / 下限类型(extends/super),提升集合操作的灵活性

(3)给老师们的建议:
老师很负责任,老师们辛苦

posted @ 2025-05-24 22:54  潇洒与浪荡  阅读(42)  评论(0)    收藏  举报