第二次Blog作业

  • 一、前言
    在完成上一次java大作业之后,我对Java各种基础知识有了更全面的认识,而第二次航空货运管理系统则是让我更加全面了解了继承与多态,接口,容器类,抽象类等Java特有的知识。接下来再分析此次作业的难度,我个人认为这次算法难度居中,比第一次作业简单很多,迭代次数也更少,大部分同学都有能力独立完成。相较于第一次作业,这次作业简单体现在于算法,单说航空货运管理系统,基本没有什么算法,大部分同学都只要花费很少的时间就能完成。

  • 二、设计与分析

第八次作业:
本次作业要求设计一个符合面向对象原则的航空货运管理系统类结构,实现客户信息管理、货物信息处理、航班管理以及订单计算与输出功能,并且确保系统具有良好的扩展性和维护性。
根据老师提供的文档,以下是关于“航空货运管理系统”题目说明的关键信息总结:

一、计费重量的确定

  • 空运货物的计费基于实际重量和体积重量中的较大值。
  • 体积重量计算公式:体积重量(kg)= 货物体积(长×宽×高,单位:厘米)÷ 6000。

二、基础运费计算

  • 运费依据计费重量乘以费率(Rate),费率根据航线、货物类型、市场行情等因素制定,例如30元/kg。
  • 采用分段计算方式,具体费率随重量区间变化而调整。

三、题目要求

  • 模拟客户办理一次货运业务的过程,包括填写货运订单并进行支付。
  • 客户需提供以下信息:
    • 客户信息(姓名、电话号码等)
    • 货物信息(名称、包装尺寸、重量等)
    • 运送信息(发件人/收件人的详细信息、所选航班号、订单日期)
    • 支付方式(如支付宝、微信支付)
  • 一个订单可包含多件货物,每件货物单独计费。

四、程序设计要求

  • 程序应从键盘输入所需的信息,并生成订单信息报表及货物明细报表。
  • 需要遵循面向对象设计原则,包括单一职责原则、里氏代换原则、开闭原则以及合成复用原则。

此题主要考察了我对面向对象设计原则的理解与在实际问题中的应用能力,对类设计的要求较高。
系统功能概述:

  1. 客户信息管理:增删改查客户信息。
  2. 货物信息处理:记录货物重量、大小、类型等。
  3. 航班管理:管理航班信息(起飞地、目的地、时间、载重限制等)。
  4. 订单计算与输出:根据客户、货物、航班生成订单,并计算运费、按格式输出。

类图如下:

分析类图可知,我严格按照题目要求,应用了面向对象设计的各个基本原则:
单一职责原则:每个类都专注于一个特定的功能或职责,huowu类只负责管理货物信息,包括货物编号、名称、重量,kehu类负责客户信息管理,如编号、姓名、地址,hangkong类负责航班信息管理,包括航班号、起飞地、目的地、最大载重和起飞时间,huodui类负责处理货队信息,包括多个货物的集合及其总重量计算,Recipient 和 Sender 类分别负责收件人和发件人的信息管理。
开闭原则:huodui类通过包含 List 来管理多个货物,这使得它可以轻松扩展以支持不同类型的货物,而无需修改其内部结构,体现了开闭原则对扩展开发,对修改关闭的特点。
里氏替换原则:Sender类和Recipient类都是Ren的子类,说明任何使用Ren类的地方都可以用Sender或Recipient替换,例如,在显示人员信息时,无论是发送者还是接收者,都可以调用 displayInfo()方法。

复杂度图如下:

代码统计信息
Lines: 文件总共有328行代码。
Statements: 总共有191个语句。
Percent Branch Statements: 分支语句占总语句的5.2%。
Method Call Statements: 方法调用语句有66个。
Percent Lines with Comments: 有5.2%的行包含注释。
Classes and Interfaces: 文件中有5个类和接口定义。
Methods per Class: 平均每个类有5.60个方法。
Average Statements per Method: 平均每个方法有5.29个语句。
复杂度分析
Line Number of Most Complex Method: 最复杂的单个方法在第66行。
Name of Most Complex Method: 最复杂的方法是Item.calculateShippingFee()。
Maximum Complexity: 最大的复杂度值为5。
Line Number of Deepest Block: 最深的代码块开始于第61行。
Maximum Block Depth: 最大嵌套深度为3。
Average Block Depth: 平均嵌套深度为1.53。
Average Complexity: 平均复杂度为1.41。
本次作业题目较简单,类设计比上次更加合理,因此不再对其分析。
源码如下:

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

// 客户类,存储客户相关信息
class Client {
    private int clientID;
    private String clientName;
    private String clientPhone;
    private String clientAddress;
    private int itemCount;

    public Client(int id, String name, String phone, String address, int count) {
        this.clientID = id;
        this.clientName = name;
        this.clientPhone = phone;
        this.clientAddress = address;
        this.itemCount = count;
    }

    public int getClientID() {
        return clientID;
    }

    public String getClientName() {
        return clientName;
    }

    public String getClientPhone() {
        return clientPhone;
    }

    public String getClientAddress() {
        return clientAddress;
    }

    public int getItemCount() {
        return itemCount;
    }
}

// 合并后的货物类,可管理多个货物并计算总重量和费用
class Item {
    private List<SingleItem> itemList;

    public Item() {
        this.itemList = new ArrayList<>();
    }

    public void addItem(SingleItem item) {
        itemList.add(item);
    }

    public int getItemListSize() {
        return itemList.size();
    }

    public double getTotalWeight() {
        double total = 0;
        for (SingleItem item : itemList) {
            total += item.getActualWeight();
        }
        return total;
    }

    public double calculateShippingFee(double weight) {
        if (weight < 20) {
            return 35;
        } else if (weight < 50) {
            return 30;
        } else if (weight < 100) {
            return 25;
        } else {
            return 15;
        }
    }

    public double calculateTotalShippingCost() {
        double total = 0;
        for (SingleItem item : itemList) {
            double fee = calculateShippingFee(item.getActualWeight());
            total += item.getActualWeight() * fee;
        }
        return total;
    }

    public void showItemDetails() {
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for (int i = 0; i < itemList.size(); i++) {
            SingleItem item = itemList.get(i);
            double fee = calculateShippingFee(item.getActualWeight());
            double cost = item.getActualWeight() * fee;
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i + 1, item.getItemName(), item.getActualWeight(), fee, cost);
        }
    }
}

// 单个货物类,存储单个货物的基本信息和计算实际重量
class SingleItem {
    private String itemID;
    private String itemName;
    private double width;
    private double length;
    private double height;
    private double actualWeight;

    public SingleItem(String id, String name, double w, double l, double h, double declaredWeight) {
        this.itemID = id;
        this.itemName = name;
        this.width = w;
        this.length = l;
        this.height = h;
        this.actualWeight = computeActualWeight(declaredWeight, w, l, h);
    }

    private double computeActualWeight(double declared, double w, double l, double h) {
        double volumeWeight = (w * l * h) / 6000;
        return Math.max(declared, volumeWeight);
    }

    public String getItemID() {
        return itemID;
    }

    public String getItemName() {
        return itemName;
    }

    public double getActualWeight() {
        return actualWeight;
    }

    public void showItemInfo() {
        System.out.println("货物编号:" + itemID);
        System.out.println("货物名称:" + itemName);
        System.out.println("货物宽度:" + width);
        System.out.println("货物长度:" + length);
        System.out.println("货物高度:" + height);
        System.out.println("货物重量:" + actualWeight);
    }
}

// 航班类,存储航班信息并检查载重限制
class FlightInfo {
    private String flightID;
    private String departurePlace;
    private String arrivalPlace;
    private double maxLoadCapacity;
    private String flightTime;

    public FlightInfo(String id, String departure, String arrival, double capacity, String time) {
        this.flightID = id;
        this.departurePlace = departure;
        this.arrivalPlace = arrival;
        this.maxLoadCapacity = capacity;
        this.flightTime = time;
    }

    public String getFlightID() {
        return flightID;
    }

    public boolean isLoadWithinCapacity(double totalWeight) {
        if (totalWeight > maxLoadCapacity) {
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.",this.flightID);
            return false;
        }
        return true;
    }

    public void showFlightDetails() {
        System.out.println("航班号:" + flightID);
    }
}

// 发件人类,存储发件人信息
class SenderInfo {
    private String senderName;
    private String senderPhone;
    private String senderAddress;

    public SenderInfo(String name, String phone, String address) {
        this.senderName = name;
        this.senderPhone = phone;
        this.senderAddress = address;
    }

    public void showSenderInfo() {
        System.out.println("发件人姓名:" + senderName);
        System.out.println("发件人电话:" + senderPhone);
        System.out.println("发件人地址:" + senderAddress);
    }
}

// 收件人类,存储收件人信息
class ReceiverInfo {
    private String receiverName;
    private String receiverPhone;
    private String receiverAddress;

    public ReceiverInfo(String name, String phone, String address) {
        this.receiverName = name;
        this.receiverPhone = phone;
        this.receiverAddress = address;
    }

    public void showReceiverInfo() {
        System.out.println("收件人姓名:" + receiverName);
        System.out.println("收件人电话:" + receiverPhone);
        System.out.println("收件人地址:" + receiverAddress);
    }
}

// 订单类,整合订单相关信息并展示订单详情
class OrderInfo {
    private int orderID;
    private String orderDate;
    private Client client;
    private FlightInfo flight;
    private SenderInfo sender;
    private ReceiverInfo receiver;
    private Item item;

    public OrderInfo(int id, String date, Client client, FlightInfo flight, SenderInfo sender, ReceiverInfo receiver, Item item) {
        this.orderID = id;
        this.orderDate = date;
        this.client = client;
        this.flight = flight;
        this.sender = sender;
        this.receiver = receiver;
        this.item = item;
    }

    public void showOrderDetails() {
        System.out.println("客户:" + client.getClientName() + "(" + client.getClientPhone() + ")订单信息如下:");
        System.out.println("-----------------------------------------");
        flight.showFlightDetails();
        System.out.println("订单号:" + orderID);
        System.out.println("订单日期:" + orderDate);
        sender.showSenderInfo();
        receiver.showReceiverInfo();
        double totalWeight = item.getTotalWeight();
        System.out.println("订单总重量(kg):" + totalWeight);
        double totalCost = item.calculateTotalShippingCost();
        System.out.println("微信支付金额:" + totalCost);

        System.out.println("\n货物明细如下:");
        System.out.println("-----------------------------------------");
        item.showItemDetails();
    }
}

// 主类,负责输入信息、创建对象和处理订单
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 输入客户信息
        int clientId = scanner.nextInt();
        scanner.nextLine();
        String clientName = scanner.nextLine();
        String clientPhone = scanner.nextLine();
        String clientAddress = scanner.nextLine();
        int itemCount = scanner.nextInt();
        scanner.nextLine();
        Client client = new Client(clientId, clientName, clientPhone, clientAddress, itemCount);

        // 输入货物信息
        Item item = new Item();
        for (int i = 1; i <= itemCount; i++) {
            String itemId = scanner.nextLine();
            String itemName = scanner.nextLine();
            double width = scanner.nextDouble();
            scanner.nextLine();
            double length = scanner.nextDouble();
            scanner.nextLine();
            double height = scanner.nextDouble();
            scanner.nextLine();
            double declaredWeight = scanner.nextDouble();
            scanner.nextLine();
            SingleItem singleItem = new SingleItem(itemId, itemName, width, length, height, declaredWeight);
            item.addItem(singleItem);
        }

        // 输入航班信息
        String flightId = scanner.nextLine();
        String departure = scanner.nextLine();
        String arrival = scanner.nextLine();
        String flightTime = scanner.nextLine();
        double maxCapacity = scanner.nextDouble();
        scanner.nextLine();
        FlightInfo flight = new FlightInfo(flightId, departure, arrival, maxCapacity, flightTime);

        // 输入订单信息
        int orderId = scanner.nextInt();
        scanner.nextLine();
        String orderDate = scanner.nextLine();

        // 输入发件人信息
        String senderAddress = scanner.nextLine();
        String senderName = scanner.nextLine();
        String senderPhone = scanner.nextLine();
        SenderInfo sender = new SenderInfo(senderName, senderPhone, senderAddress);

        // 输入收件人信息
        String receiverAddress = scanner.nextLine();
        String receiverName = scanner.nextLine();
        String receiverPhone = scanner.nextLine();
        ReceiverInfo receiver = new ReceiverInfo(receiverName, receiverPhone, receiverAddress);

        // 计算订单总重量
        double totalWeight = item.getTotalWeight();

        // 检查货物总重量是否超过飞机最大载重量
        if (!flight.isLoadWithinCapacity(totalWeight)) {
            scanner.close();
            return;
        }

        // 创建订单对象
        OrderInfo order = new OrderInfo(orderId, orderDate, client, flight, sender, receiver, item);

        // 展示订单信息
        order.showOrderDetails();

        scanner.close();
    }
}    

第九次作业:
本次作业是上一次作业的迭代,其中费率与货物类型有关,货物类型分为普通货物、危险货物和加急货物三种,每种货物对应不同的费率,用户分为两种,个人用户和集团用户,同时还添加了现金支付方式,并且运用了Java中抽象类的知识。相较于前一次作业,区别如下::

  1. 基础运费计算
    • 增加了货物类型的区分:普通货物、危险货物和加急货物三种类型。
    • 引入了折扣率的概念,基于用户类型(个人用户享受9折优惠,集团用户享受8折优惠)。
  2. 设计原则
    • 在原有基础上新增了依赖倒转原则(Dependency Inversion Principle, DIP),作为考核标准之一。现在总共有五个面向对象设计原则需要考虑:
  3. 支付方式
    • 支付方式中增加了“现金支付”的选项,原只有支付宝支付、微信支付两种选择。

比较分析

  • 基础运费计算方面:第二次题目中明确了不同货物类型的费率差异,并引入了用户类型相关的折扣机制,使得运费计算更加复杂且贴近实际情况。

  • 题目要求方面:除了强调运费计算逻辑的变化外,还特别指出了系统设计应遵循的五项面向对象设计原则,特别是新增了对依赖倒转原则的关注。这表明对我的设计能力提出了更高的要求。

第二次题目不仅细化了运费计算规则,而且进一步强化了面向对象设计原则的应用。

类图如下:


分析三张类图可知,本次作业的代码与前一次作业代码区别不大,只是新增order类,并且使用了抽象类与接口,难度相较于前一次作业更低,更是远远比不上第五到第七次作业中电梯系统的迭代,只要上课认真听课,课后有积极完成老师在课堂上的作业和在pta发布的题目,应该都能轻松此次作业。

复杂度图如下:

代码统计信息
Lines: 文件总共有581行代码。
Statements: 总共有271个语句。
Percent Branch Statements: 分支语句占总语句的8.5%。
Method Call Statements: 方法调用语句有38个。
Percent Lines with Comments: 有3.4%的行包含注释。
Classes and Interfaces: 文件中有12个类和接口定义。
Methods per Class: 平均每个类有10.75个方法。
Average Statements per Method: 平均每个方法有2.02个语句。
复杂度分析
Line Number of Most Complex Method: 最复杂的单个方法在第0行(可能是由于统计方式导致的异常值)。
Name of Most Complex Method: 最复杂的方法是Dangerous.getCargos()。
Maximum Complexity: 最大的复杂度值为5。
Line Number of Deepest Block: 最深的代码块开始于第202行。
Maximum Block Depth: 最大嵌套深度为3。
Average Block Depth: 平均嵌套深度为1.32。
Average Complexity: 平均复杂度为1.80。

对比两次作业,代码的平均复杂度相差不大,总体上与前一次作业大差不差,说明两次类设计都较为合理。

源码如下:

点击查看代码
import java.util.*;

// 基类:人
abstract class Person {
    protected String name;
    protected String phone;
    protected String address;

    public Person(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 extends Person {
    private String customerID;

    public Customer(String customerID, String name, String address, String phone) {
        super(name, phone, address);
        this.customerID = customerID;
    }

    public String getCustomerID() {
        return customerID;
    }
    public String getCustomerName() {
        return name;
    }
    public String getCustomerPhone() {
        return phone;
    }

}

// 发件人类
class Sender extends Person {
    public Sender(String name, String phone, String address) {
        super(name, phone, address);
    }
}

// 收件人类
class Receiver extends Person {
    public Receiver(String name, String phone, String address) {
        super(name, phone, address);
    }
}

// 货物类
class Cargo {
    private String cargoType;
    private String cargoID;
    private String cargoName;
    private double cargoWidth;
    private double cargoLength;
    private double cargoHeight;
    private double cargoWeight;

    public Cargo(String cargoType, String cargoID, String cargoName, double cargoWidth, double cargoLength, double cargoHeight, double cargoWeight) {
        this.cargoType = cargoType;
        this.cargoID = cargoID;
        this.cargoName = cargoName;
        this.cargoWidth = cargoWidth;
        this.cargoLength = cargoLength;
        this.cargoHeight = cargoHeight;
        this.cargoWeight = cargoWeight;
    }

    public String getCargoType() {
        return cargoType;
    }

    public String getCargoID() {
        return cargoID;
    }

    public String getCargoName() {
        return cargoName;
    }

    public double getCargoWidth() {
        return cargoWidth;
    }

    public double getCargoLength() {
        return cargoLength;
    }

    public double getCargoHeight() {
        return cargoHeight;
    }

    public double getCargoWeight() {
        return cargoWeight;
    }
}

// 航班类
class Flight {
    private String flightID;
    private String departAirport;
    private String arrivalAirport;
    private String departureTime;
    private double maxLoad;
    private double currentLoad;

    public Flight(String flightID, String departAirport, String arrivalAirport, String departureTime, double maxLoad) {
        this.flightID = flightID;
        this.departAirport = departAirport;
        this.arrivalAirport = arrivalAirport;
        this.departureTime = departureTime;
        this.maxLoad = maxLoad;
        this.currentLoad = 0.0;
    }

    public String getFlightID() {
        return flightID;
    }

    public double getMaxLoad() {
        return maxLoad;
    }

    public double getCurrentLoad() {
        return currentLoad;
    }

    public void addLoad(double weight) {
        currentLoad += weight;
    }

    public boolean canCarry(double weight) {
        return currentLoad + weight <= maxLoad;
    }
}

// 订单类
class Order {
    private String orderID;
    private String orderDate;
    private Sender sender;
    private Receiver receiver;
    private List<Cargo> cargos;

    public Order(String orderID, String orderDate, Sender sender, Receiver receiver, List<Cargo> cargos) {
        this.orderID = orderID;
        this.orderDate = orderDate;
        this.sender = sender;
        this.receiver = receiver;
        this.cargos = cargos;
    }

    public String getOrderID() {
        return orderID;
    }

    public String getOrderDate() {
        return orderDate;
    }

    public Sender getSender() {
        return sender;
    }

    public Receiver getReceiver() {
        return receiver;
    }

    public List<Cargo> getCargos() {
        return cargos;
    }
}

// 费率策略接口
interface RateStrategy {
    double calculateVolumeWeight(Cargo cargo);
    double getRate(double chargeWeight);
    double calculateFreight(double chargeWeight);
}

class Normal implements RateStrategy {
    @Override
    public double calculateVolumeWeight(Cargo cargo) {
        double volume = cargo.getCargoWidth() * cargo.getCargoLength() * cargo.getCargoHeight();
        double volumeWeight = volume / 6000.0;
        return volumeWeight ;
    }
    @Override
    public double getRate(double chargeWeight) {
        if (chargeWeight < 20) {
            return 35;
        } else if (chargeWeight < 50) {
            return 30;
        } else if (chargeWeight < 100) {
            return 25;
        } else {
            return 15;
        }
    }
    @Override
    public double calculateFreight(double chargeWeight) {
        double rate = getRate(chargeWeight);
        return chargeWeight * rate;
    }
}

class Expedite implements RateStrategy {

    @Override
    public double calculateVolumeWeight(Cargo cargo) {
        double volume = cargo.getCargoWidth() * cargo.getCargoLength() * cargo.getCargoHeight();
        double volumeWeight = volume / 6000.0;
        return volumeWeight ;
    }

    @Override
    public double getRate(double chargeWeight) {
        if (chargeWeight < 20) {
            return 60;
        } else if (chargeWeight < 50) {
            return 50;
        } else if (chargeWeight < 100) {
            return 40;
        } else {
            return 30;
        }
    }

    @Override
    public double calculateFreight(double chargeWeight) {
        double rate = getRate(chargeWeight);
        return chargeWeight * rate ;
    }
}

class  Dangerous implements RateStrategy {

    @Override
    public double calculateVolumeWeight(Cargo cargo) {
        double volume = cargo.getCargoWidth() * cargo.getCargoLength() * cargo.getCargoHeight();
        double volumeWeight = volume / 6000.0;
        return volumeWeight;
    }

    @Override
    public double getRate(double chargeWeight) {
        if (chargeWeight < 20) {
            return 80;
        } else if (chargeWeight < 50) {
            return 50;
        } else if (chargeWeight < 100) {
            return 30;
        } else {
            return 20;
        }
    }

    @Override
    public double calculateFreight(double chargeWeight) {
        double rate = getRate(chargeWeight);
        return chargeWeight * rate;
    }
}
// 标准费率策略
class StandardRate implements RateStrategy {
    @Override
    public double calculateVolumeWeight(Cargo cargo) {
        double volume = cargo.getCargoWidth() * cargo.getCargoLength() * cargo.getCargoHeight();
        double volumeWeight = volume / 6000.0;
        return volumeWeight;
    }

    @Override
    public double getRate(double chargeWeight) {
        if (chargeWeight < 20) {
            return 35;
        } else if (chargeWeight < 50) {
            return 30;
        } else if (chargeWeight < 100) {
            return 25;
        } else {
            return 15;
        }
    }

    @Override
    public double calculateFreight(double chargeWeight) {
        double rate = getRate(chargeWeight);
        return chargeWeight * rate ;
    }
}

// 折扣费率策略
class DiscountRate implements RateStrategy {
    private double discountRate;
    private RateStrategy baseRate;

    public DiscountRate(String people, RateStrategy baseRate) {
        this.baseRate = baseRate;
        setDiscountRate(people);
    }

    private void setDiscountRate(String people) {
        if (people.equals("Individual")) {
            this.discountRate = 0.9;
        } else {
            this.discountRate = 0.8;
        }
    }

    @Override
    public double calculateVolumeWeight(Cargo cargo) {
        return baseRate.calculateVolumeWeight(cargo);
    }

    @Override
    public double getRate(double chargeWeight) {
        return baseRate.getRate(chargeWeight);
    }

    @Override
    public double calculateFreight(double chargeWeight) {
        return baseRate.calculateFreight(chargeWeight) * discountRate ;
    }
}

// 支付接口
interface Payment {
    String getPaymentName();
}

// 微信支付
class WechatPayment implements Payment {
    @Override
    public String getPaymentName() {
        return "微信";
    }
}

// 支付宝支付
class AlipayPayment implements Payment {
    @Override
    public String getPaymentName() {
        return "支付宝";
    }
}

// 现金支付
class CashPayment implements Payment {
    @Override
    public String getPaymentName() {
        return "现金";
    }
}

// 支付工厂
class PaymentFactory {
    public static Payment createPayment(String paymentMethod) {
        return switch (paymentMethod) {
            case "Wechat" -> new WechatPayment();
            case "ALiPay" -> new AlipayPayment();
            default -> new CashPayment();
        };
    }
}

class Check{
    private Flight flight;
    List<Cargo> cargos=new ArrayList<>();
    public Check(Flight flight, List<Cargo> cargos) {
        this.flight = flight;
        this.cargos=cargos;
    }
    public boolean Checkweight(){
        for (Cargo cargo : cargos) {
            double volumeWeight = cargo.getCargoWidth() * cargo.getCargoLength() * cargo.getCargoHeight() / 6000.0;
            double chargeWeight = Math.max(volumeWeight, cargo.getCargoWeight());
            if (!flight.canCarry(chargeWeight)) {
                System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flight.getFlightID());
                return false;
            }
            flight.addLoad(chargeWeight);
        }
        return true;
    }
}
class Agent{
    private String cargoType;
    private String people;
    public Agent(String cargoType, String people) {
        this.cargoType = cargoType;
        this.people = people;
    }
    public RateStrategy getRateStrategy() {
        RateStrategy rateStrategy;
        if(cargoType.equals("Normal")) {
            Normal standardRate = new Normal();
            rateStrategy = new DiscountRate(people, standardRate);
        }else{
            if(cargoType.equals("Expedite"))
            {
                Expedite standardRate = new Expedite();
                rateStrategy = new DiscountRate(people, standardRate);
            }
            else {
                Dangerous standardRate = new Dangerous();
                rateStrategy = new DiscountRate(people, standardRate);
            }
        }
        return rateStrategy;
    }
    public RateStrategy getRateStrategy1() {
        RateStrategy rateStrategy1;
        if(cargoType.equals("Normal")) {
            Normal standardRate = new Normal();
            rateStrategy1 = standardRate;
        }else{
            if(cargoType.equals("Expedite"))
            {
                Expedite standardRate = new Expedite();
                rateStrategy1 = standardRate;
            }
            else {
                Dangerous standardRate = new Dangerous();
                rateStrategy1 = standardRate;
            }
        }
        return rateStrategy1;
    }
}
class Display{
    private Customer customer;
    private List<Cargo> cargos=new ArrayList<>();
    private Sender sender;
    private Receiver receiver;
    private Flight flight;
    private Order order;
    private  RateStrategy rateStrategy;
    private  RateStrategy rateStrategy1;
    private Payment payment;
    public Display(Payment payment,Customer customer,List<Cargo> cargos,Sender sender,Receiver receiver,Flight flight,Order order,RateStrategy rateStrategy,RateStrategy rateStrategy1)
    {
        this.customer=customer;
        this.cargos=cargos;
        this.sender=sender;
        this.receiver=receiver;
        this.flight=flight;
        this.order=order;
        this.payment=payment;
        this.rateStrategy=rateStrategy;
        this.rateStrategy1=rateStrategy1;
    }
    public void display()
    {
        double totalFreight = 0.0;
        double totalChargeWeight = 0.0;
        List<String> details = new ArrayList<>();

        for (int i = 0; i < cargos.size(); i++) {
            Cargo cargo = cargos.get(i);
            double volumeWeight = rateStrategy.calculateVolumeWeight(cargo);
            double actualWeight = cargo.getCargoWeight();
            double chargeWeight = Math.max(volumeWeight, actualWeight);
            totalChargeWeight += chargeWeight;

            double freight = rateStrategy.calculateFreight(chargeWeight);
            totalFreight += freight;
            freight = rateStrategy1.calculateFreight(chargeWeight);
            String detail = String.format("%d\t%s\t%.1f\t%.1f\t%.1f",
                    i + 1, cargo.getCargoName(), chargeWeight,
                    rateStrategy.getRate(chargeWeight), freight);
            details.add(detail);
        }

        System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getCustomerName(), customer.getCustomerPhone());
        System.out.println("-----------------------------------------");
        System.out.printf("航班号:%s\n", flight.getFlightID());
        System.out.printf("订单号:%s\n", order.getOrderID());
        System.out.printf("订单日期:%s\n", order.getOrderDate());
        System.out.printf("发件人姓名:%s\n", sender.getName());
        System.out.printf("发件人电话:%s\n", sender.getPhone());
        System.out.printf("发件人地址:%s\n", sender.getAddress());
        System.out.printf("收件人姓名:%s\n", receiver.getName());
        System.out.printf("收件人电话:%s\n", receiver.getPhone());
        System.out.printf("收件人地址:%s\n", receiver.getAddress());
        System.out.printf("订单总重量(kg):%.1f\n", totalChargeWeight);
        System.out.printf("%s支付金额:%.1f\n", payment.getPaymentName(), totalFreight);
        System.out.println();
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for(int i=0;i<details.size();i++)
        {
            if(i<details.size()-1)
                System.out.println(details.get(i));
            else
                System.out.printf(details.get(i));
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        String people = cin.nextLine().trim();

        // 读取客户信息
        String customerID = cin.nextLine().trim();
        String customerName = cin.nextLine().trim();
        String customerPhone = cin.nextLine().trim();
        String customerAddress = cin.nextLine().trim();
        Customer customer = new Customer(customerID, customerName, customerAddress, customerPhone);

        // 读取货物信息
        String cargoType = cin.nextLine().trim();
        int cargoCount = Integer.parseInt(cin.nextLine().trim());
        List<Cargo> cargos = new ArrayList<>();
        for (int i = 0; i < cargoCount; i++) {
            String cargoID = cin.nextLine().trim();
            String cargoName = cin.nextLine().trim();
            double width = Double.parseDouble(cin.nextLine().trim());
            double length = Double.parseDouble(cin.nextLine().trim());
            double height = Double.parseDouble(cin.nextLine().trim());
            double weight = Double.parseDouble(cin.nextLine().trim());
            cargos.add(new Cargo(cargoType, cargoID, cargoName, width, length, height, weight));
        }

        // 读取航班信息
        String flightID = cin.nextLine().trim();
        String departAirport = cin.nextLine().trim();
        String arrivalAirport = cin.nextLine().trim();
        String departureTime = cin.nextLine().trim();
        double maxLoad = Double.parseDouble(cin.nextLine().trim());
        Flight flight = new Flight(flightID, departAirport, arrivalAirport, departureTime, maxLoad);

        // 检查航班载重量
        Check check = new Check(flight, cargos);
        if(!check.Checkweight()){
            return ;
        }

        // 读取订单信息
        String orderID = cin.nextLine().trim();
        String orderDate = cin.nextLine().trim();
        String senderAddress = cin.nextLine().trim();
        String senderName = cin.nextLine().trim();
        String senderPhone = cin.nextLine().trim();
        String receiverAddress = cin.nextLine().trim();
        String receiverName = cin.nextLine().trim();
        String receiverPhone = cin.nextLine().trim();
        Sender sender = new Sender(senderName, senderPhone, senderAddress);
        Receiver receiver = new Receiver(receiverName, receiverPhone, receiverAddress);
        Order order = new Order(orderID, orderDate, sender, receiver, cargos);

        //支付方式
        String paymentMethod = cin.nextLine().trim();
        Payment payment = PaymentFactory.createPayment(paymentMethod);

        // 计算运费
        Agent agent=new Agent(cargoType,people);
        RateStrategy rateStrategy= agent.getRateStrategy();
        RateStrategy rateStrategy1=agent.getRateStrategy1();

        Display display=new Display(payment,customer,cargos,sender,receiver,flight,order,rateStrategy,rateStrategy1);
        display.display();
    }
}
  • 三、踩坑总结
    在这两次作业中,六个题目的难度都不大,甚至可以说是简单,第八次作业中点线面问题重构和雨刷程序功能扩展设计两个题目都是重点考察继承与多态,第三个题目航空货运管理系统(类设计)则是考察合理设计类与类之间的关系,第九次作业中魔方问题同样是在考察继承与多态,而点线面问题再重构则是考察我们对容器类的使用,最后一个题目航空货运管理系统(继承与多态)是对前一次题目的迭代,在这六个题目中,我在第三个题目也就是航空货运管理系统(类设计)这个题目花费了最多时间,原因是输出格式错误,题目输出时要求的符号是英文字符,我用的却是英文字符,导致一直在检查代码中是否有逻辑错误,花费了很多天的时间。

  • 四、心得体会
    这两次作业虽然难度不大,但是其中却包含了很多知识,类的设计,继承与多态,抽象类与接口,容器类等等,并且我也发现了我的不足:代码的书写能力较差,很多英语单词拼写不正确,并且经常不遵循命名资格来命名。

  • 五、总结
    在完成第八次和第九次作业的过程中,我对 Java 编程语言的理解与应用能力得到了显著提升,尤其是在继承、多态等面向对象编程的核心概念方面。通过这两项作业的实践训练,我能够更加熟练地编写结构清晰、逻辑严谨的代码,并迅速实现具有一定复杂度的功能模块。
    这两次作业的核心任务是模拟客户办理航空货运业务的全过程。基于这一需求,我需要设计并实现一个完整的面向对象系统。这个系统不仅要满足基本功能要求,还必须符合多项面向对象设计原则,如单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)以及依赖倒置原则(DIP)。这些原则的贯彻执行,使得我在软件架构层面有了更深入的理解,也提升了我在模块化设计、代码复用和系统扩展性方面的意识。
    在开发过程中,我特别注重采用良好的设计模式来优化系统的结构,例如工厂模式(Factory Pattern)用于对象的创建,策略模式(Strategy Pattern)用于行为的动态切换,观察者模式(Observer Pattern)用于事件驱动的设计等。这些设计模式的合理运用,不仅提高了系统的可维护性和可扩展性,也为后续的功能迭代打下了坚实的基础。
    总的来说,这两次作业不仅帮助我巩固了 Java 编程的基本功,更重要的是培养了我从更高层次去思考软件设计与架构的能力。这种理论与实践相结合的学习方式,极大地提升了我的综合编程素养,为今后参与更复杂的软件开发项目奠定了坚实的基础。

posted @ 2025-05-25 23:35  好喜欢学校  阅读(9)  评论(0)    收藏  举报