difeny

 

第二次blog作业

一,前言

两次关于航空货运管理系统的大作业,第一次为基础版,重点考查类的封装、计费逻辑实现及单一职责、合成复用原则的初步应用,涉及客户、航班、货物、订单等类的定义与基础输入输出流程,;第二次假设为深化版,在第一次基础上扩展设计原则深度,增加枚举、异常处理等进阶语法,代码复杂度与设计挑战提升。总的来说难度不是很大,但是代码量很多,要求码力也比之前高,完成还是需要花不少时间。但是自己一点一点打出来收获还是很大的。

二,设计过程

第一次作业

看题目给的输入和输出都很长,可见要求的代码有多少

下面是ac代码

点击查看代码
import java.util.*;
class Customer{
    String id;
    String name;
    String phone;
    String address;
    public Customer(String id, String name, String phone, String address){
        this.id = id;
        this.name = name;
        this.phone = phone;
        this.address = address;
    }
}
class Cargo{
    String id;
    String name;
    double width;
    double length;
    double height;
    double weight;
    public Cargo(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;
    }
    double getWeight(){
        return Math.max(width * height * length/6000,weight);
    }
    double getV()
    {
        double x=getWeight();
        if(x<20)return x*35;
        if(x<50)return x*30;
        if(x<100)return x*25;
        return x*15;
    }
}
class Flight{
    String id;
    String strat;
    String end;
    String date;
    double maxweight;
    public Flight(String id, String strat, String end, String date, double maxweight){
        this.id = id;
        this.strat = strat;
        this.end = end;
        this.date = date;
        this.maxweight = maxweight;
    }
}
class Order {

    String id;
    String date;
    String address1;
    String name1;
    String phone1;

    String address2;
    String name2;
    String phone2;
    List<Cargo> cargo;
    public Order(String id, String date, String address1, String name1, String phone1, String address2, String name2, String phone2,List<Cargo> cargo) {

        this.id = id;
        this.date = date;
        this.address1 = address1;
        this.name1 = name1;
        this.phone1 = phone1;
        this.address2 = address2;
        this.name2 = name2;
        this.phone2 = phone2;
        this.cargo = cargo;
    }
    double getWeight(){
        double res=0;
        for(Cargo cargo :cargo){
            res+=cargo.getWeight();
        }
        return res;
    }
    double getV(){
        double res=0;
        for(Cargo cargo :cargo){
            res+=cargo.getV();
        }
        return res;
    }
}
public class Main{
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 输入客户信息
        String customerId = scanner.nextLine();
        String customerName = scanner.nextLine();
        String customerPhone = scanner.nextLine();
        String customerAddress = scanner.nextLine();
        Customer customer = new Customer(customerId, customerName, customerPhone, customerAddress);

        // 输入货物信息
        int cargoCount = Integer.parseInt(scanner.nextLine());
        List<Cargo> cargoList = new ArrayList<>();
        for (int i = 0; i < cargoCount; i++) {
            String cargoId = scanner.nextLine();
            String cargoName = 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());
            Cargo cargo = new Cargo(cargoId, cargoName, width, length, height, weight);
            cargoList.add(cargo);
        }

       
        String flightNumber = scanner.nextLine();
        String departureAirport = scanner.nextLine();
        String arrivalAirport = scanner.nextLine();
        String flightDate = scanner.nextLine();
        double maxWeight = Double.parseDouble(scanner.nextLine());
        Flight flight = new Flight(flightNumber, departureAirport, arrivalAirport, flightDate, maxWeight);

       
        String orderId = scanner.nextLine();
        String orderDate = scanner.nextLine();
        String senderAddress = scanner.nextLine();
        String senderName = scanner.nextLine();
        String senderPhone = scanner.nextLine();
        String recipientAddress = scanner.nextLine();
        String recipientName = scanner.nextLine();
        String recipientPhone = scanner.nextLine();
        Order order = new Order(orderId, orderDate, senderAddress, senderName, senderPhone,
                recipientAddress, recipientName, recipientPhone, cargoList);

        if (order.getWeight() > flight.maxweight) {
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.\n", flightNumber);
            return;
        }

    
        System.out.printf("客户:%s(%s)订单信息如下:\n", customerName, customerPhone);
        System.out.println("-----------------------------------------");
        System.out.printf("航班号:%s\n", flightNumber);
        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", ExpeditesenderAddress);
        System.out.printf("收件人姓名:%s\n", recipientName);
        System.out.printf("收件人电话:%s\n", recipientPhone);
        System.out.printf("收件人地址:%s\n", recipientAddress);
        System.out.printf("订单总重量(kg):%.1f\n", order.getWeight());
        System.out.printf("微信支付金额:%.1f\n\n", order.getV());

        // 输出货物明细
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号	货物名称	计费重量	计费费率	应交运费");
        for (int i = 0; i < cargoList.size(); i++) {
            Cargo cargo = cargoList.get(i);
            double chargeableWeight = cargo.getWeight();
            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	%s	%.1f	%.1f	%.1f\n", i + 1, cargo.name, chargeableWeight, rate, cargo.getV());
        }
    }
}

###类的设计分析

核心实体类

Customer类

封装客户基本信息(ID、姓名、电话、地址),遵循单一职责原则。

Flight类

管理航班信息类
(航班号、起降机场、日期、最大载重),提供载重校验方法。

Cargo类 抽象基类,定义货物通用属性(尺寸、重量)和计费逻辑(体积重量、计费重量)。

NormalCargo类

普通货物子类,实现具体运费计算(基于重量分段计价)。

DangerousCargo类

危险品子类,扩展特殊货物的计费规则(如附加费)。

Order类

整合订单信息(发件人、收件人、航班)和货物列表,计算总重量与总费用。

sourcemonitor解析代码


行数:179 行
语句数:127 条
分支语句百分比:5.5% ,意味着约四分之一语句是分支逻辑(if-else)
方法调用语句数:42 条
注释行百分比:0.0% ,即代码无注释
类和接口数量:5 个
每个类的平均方法数:2.80 个
每个方法的平均语句数):10.43条
最复杂方法的行号:77 行,方法为 Elevator.getNextTargetFloor()
最大复杂度为43,方法也是Elevator.getNextTargetFloor()
最深代码块行号:91 行
最大代码块深度为5
平均代码块深度:2.93
平均复杂度:6.21

第二次作业

ac代码

点击查看代码
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;
    private String type;

    public Customer(String id, String name, String phone, String address, String type) {
        this.id = id;
        this.name = name;
        this.phone = phone;
        this.address = address;
        this.type = type;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public String getType() {
        return type;
    }
}


class Cargo {
    private String id;
    private String name;
    private double width;
    private double length;
    private double height;
    private double weight;
    private String type; 

    String getName()
    {
        return name;
    }
    public Cargo(String id, String name, double width, double length, double height, double weight, String type) {
        this.id = id;
        this.name = name;
        this.width = width;
        this.length = length;
        this.height = height;
        this.weight = weight;
        this.type = type;
    }


    public double getVolumeWeight() {
        return (width * length * height) / 6000;
    }


    public double getChargeableWeight() {
        return Math.max(weight, getVolumeWeight());
    }

  
    public double getBaseCost() {
        double rate = getRate();
        return getChargeableWeight() * rate;
    }

 
     double getRate() {
        double v=getChargeableWeight();
        if ("Normal".equals(type)) {
            if(v<20)return 35.0;
            if(v<50)return 30;
            if(v<100)return 25;
            return 15;
        } else if ("Expedite".equals(type)) {
            if(v<20)return 60;
            if(v<50)return 50;
            if(v<100)return 40;
            return 30;
        } else if ("Dangerous".equals(type)) {
            if(v<20)return 80;
            if(v<50)return 50;
            if(v<100)return 30;
            return 20;
        }
        return 0.0;
    }
}

class Flight {
    private String id;
    private String departureAirport;
    private String arrivalAirport;
    private String date;
    private double maxWeight;

    public Flight(String id, String departureAirport, String arrivalAirport, String date, double maxWeight) {
        this.id = id;
        this.departureAirport = departureAirport;
        this.arrivalAirport = arrivalAirport;
        this.date = date;
        this.maxWeight = maxWeight;
    }

    public String getId() {
        return id;
    }

    public String getDepartureAirport() {
        return departureAirport;
    }

    public String getArrivalAirport() {
        return arrivalAirport;
    }

    public String getDate() {
        return date;
    }

    public double getMaxWeight() {
        return maxWeight;
    }
}


class Order {
    private String id;
    private String date;
    private String senderAddress;
    private String senderName;
    private String senderPhone;
    private String recipientAddress;
    private String recipientName;
    private String recipientPhone;
    private String paymentMethod;
    private List<Cargo> cargoList;

    public Order(String id, String date, String senderAddress, String senderName,
                 String senderPhone, String recipientAddress, String recipientName,
                 String recipientPhone, String paymentMethod, List<Cargo> cargoList) {
        this.id = id;
        this.date = date;
        this.senderAddress = senderAddress;
        this.senderName = senderName;
        this.senderPhone = senderPhone;
        this.recipientAddress = recipientAddress;
        this.recipientName = recipientName;
        this.recipientPhone = recipientPhone;
        this.paymentMethod = paymentMethod;
        this.cargoList = cargoList;
    }

    public double getTotalWeight() {
        double totalWeight = 0;
        for (Cargo cargo : cargoList) {
            totalWeight += cargo.getChargeableWeight();
        }
        return totalWeight;
    }


    public double getTotalCost(Customer customer) {
        double totalCost = 0;
        for (Cargo cargo : cargoList) {
            totalCost += cargo.getBaseCost();
        }
        
        if ("Individual".equals(customer.getType())) {
            totalCost *= 0.9; 
        } else if ("Corporate".equals(customer.getType())) {
            totalCost *= 0.8; 
        }
        return totalCost;
    }
}

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


        String customerType = scanner.nextLine();
        String customerId = scanner.nextLine();
        String customerName = scanner.nextLine();
        String customerPhone = scanner.nextLine();
        String customerAddress = scanner.nextLine();
        Customer customer = new Customer(customerId, customerName, customerPhone, customerAddress, customerType);


        String cargoType = scanner.nextLine();
        int cargoCount = Integer.parseInt(scanner.nextLine());
        List<Cargo> cargoList = new ArrayList<>();
        for (int i = 0; i < cargoCount; i++) {
            String cargoId = scanner.nextLine();
            String cargoName = 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());
            Cargo cargo = new Cargo(cargoId, cargoName, width, length, height, weight, cargoType);
            cargoList.add(cargo);
        }


        String flightId = scanner.nextLine();
        String departureAirport = scanner.nextLine();
        String arrivalAirport = scanner.nextLine();
        String flightDate = scanner.nextLine();
        double maxWeight = Double.parseDouble(scanner.nextLine());
        Flight flight = new Flight(flightId, departureAirport, arrivalAirport, flightDate, maxWeight);

        String orderId = scanner.nextLine();
        String orderDate = scanner.nextLine();
        String senderAddress = scanner.nextLine();
        String senderName = scanner.nextLine();
        String senderPhone = scanner.nextLine();
        String recipientAddress = scanner.nextLine();
        String recipientName = scanner.nextLine();
        String recipientPhone = scanner.nextLine();
        String paymentMethod = scanner.nextLine();
        Order order = new Order(orderId, orderDate, senderAddress, senderName, senderPhone, recipientAddress, recipientName, recipientPhone, paymentMethod, cargoList);


        if (order.getTotalWeight() > flight.getMaxWeight()) {
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flight.getId());
            System.exit(0);
        } else {
        
            System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getName(), customer.getPhone());
            System.out.println("-----------------------------------------");
            System.out.printf("航班号:%s\n", flight.getId());
            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", recipientName);
            System.out.printf("收件人电话:%s\n", recipientPhone);
            System.out.printf("收件人地址:%s\n", recipientAddress);
            System.out.printf("订单总重量(kg):%.1f\n", order.getTotalWeight());
            if(paymentMethod.equals("Wechat"))System.out.printf("微信");
            if(paymentMethod.equals("ALiPay"))System.out.printf("支付宝");
            if(paymentMethod.equals("Cash"))System.out.printf("现金");
            System.out.printf("支付金额:%.1f\n\n",  order.getTotalCost(customer));

            System.out.println("货物明细如下:");
            System.out.println("-----------------------------------------");
            System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
            for (int i = 0; i < cargoList.size(); i++) {
                Cargo cargo = cargoList.get(i);
                System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i + 1, cargo.getName(), cargo.getChargeableWeight(), cargo.getRate(), cargo.getBaseCost());
            }
        }
    }
}
###类的设计分析 核心类功能细节

1. Customer 类

属性:客户编号、姓名、电话、地址、类型(Individual/Corporate)。
作用:
区分客户类型以应用不同折扣(个人 9 折、企业 8 折)。
提供客户基本信息用于订单报表输出。

2. Cargo 类

属性:货物编号、名称、宽度、长度、高度、实际重量、类型(Normal/Expedite/Dangerous)。
核心方法:
getVolumeWeight():计算体积重量(长 × 宽 × 高 ÷6000)。
getChargeableWeight():取体积重量与实际重量的较大值作为计费重量。
getBaseCost():根据货物类型和计费重量计算基础运费(分段费率)。

3. Flight 类

属性:航班号、起飞机场、降落机场、日期、最大载重量。
作用:
存储航班基础信息。
提供getMaxWeight()方法校验订单总重量是否超过航班载重限制。

4. Order 类

属性:订单号、日期、收发件人信息、支付方式、货物列表。
核心方法:
getTotalWeight():累加所有货物的计费重量,计算订单总重量。
getTotalCost(Customer):根据客户类型计算总费用(基础运费 + 折扣)。

5. Main 类

职责:
按顺序读取用户输入(客户、货物、航班、订单信息)。
实例化各业务对象,调用Flight校验载重。
格式化输出订单信息和货物明细,处理载重超限异常。

sourcemonitor解析代码


行数:271 行
语句数:197 条
分支语句百分比:11.2% ,意味着约四分之一语句是分支逻辑(if-else)
方法调用语句数:67 条
注释行百分比:0.0% ,即代码无注释
类和接口数量:5 个
每个类的平均方法数:3.80 个
每个方法的平均语句数):9.43条
最复杂方法的行号:77 行,方法为 Elevator.getNextTargetFloor()
最大复杂度为43,方法也是Elevator.getNextTargetFloor()
最深代码块行号:81 行
最大代码块深度为5
平均代码块深度:2.93
平均复杂度:6.21

3,踩坑心得

一、输入输出处理的坑

  1. 输入顺序混乱
    坑:未严格按照题目要求的顺序输入数据,导致Scanner读取错位(如先输入货物数量却先读取货物类型)。
    心得:
    用注释明确标注输入步骤(如 “// 输入客户信息”“// 输入货物信息”)。
    每次读取后打印临时变量值,调试确认输入顺序正确(如System.out.println("读取的货物数量:" + cargoCount))。
  2. 数据类型转换错误
    坑:字符串转数值时未处理非法输入(如输入字母导致NumberFormatException)。
    心得:
    增加异常捕获(try-catch),提示用户重新输入合法数值。
    输入后立即校验范围(如if (weight <= 0) throw new IllegalArgumentException("重量必须为正数"))。
  3. 输出格式控制
    坑:浮点型输出未保留指定小数位(如%.1f写成%.0f),或对齐混乱(制表符\t使用不当)。
    心得:
    使用System.out.printf("%.1f", value)强制格式化,提前测试边界值(如计费重量为整数时显示.0)。
    用文本编辑器先模拟表格对齐(如 Excel 或 Markdown 表格),再转化为printf格式。

4,改进建议

一、设计原则优化
单一职责原则
拆分Cargo类中费率计算逻辑,避免同时处理属性和计费规则。
将支付方式输出逻辑从Order类分离,避免职责混杂。
开闭原则
用策略模式封装货物费率计算(定义接口FreightStrategy,不同类型货物实现接口)。
新增货物类型时通过扩展策略类实现,不修改原有代码。
里氏代换原则
若存在子类(如危险品),确保父类Cargo的核心方法(如计费)行为一致,子类可安全替换父类。
合成复用原则
避免继承滥用,通过组合(如Order包含Cargo列表)实现代码复用。
二、代码规范与可读性
命名规范
方法名更直观:getV()→calculateFreight(),strat→departureAirport。
类名、变量名遵循驼峰命名(如cargoCount而非cargoCount,已正确)。
数据封装
所有字段声明为private,通过public getter/setter访问(如Customer类添加getType())。
注释补充
关键逻辑添加注释:费率分段依据、折扣规则、体积重量公式来源。

5,总结

写大作业不要骄躁,一步一步来,才能收获多

posted on 2025-05-25 21:25  difeny  阅读(15)  评论(0)    收藏  举报

导航