前言

知识点:

1、类的封装
2、继承与多态
3、List的用法

题量

每次题目集三道题,其中两道小程序题,一道迭代性大作业,作业题量不算多

难度

第一次(这次大作业中的第一次)大作业我觉得是考核类的封装,并没有太大的逻辑问题,静下心去慢慢写是可以写出来的,唯一要注意的就是费率的边界问题,当时第一个大作业的一个费率边界错了,第二个测试点硬是过不去,而且也没有提示第二个测试点是测试什么,我一直认识是数据类型错了,找了一天才发现是边界的一个等号划错了地方。

第二次(这次大作业中的第二次)大作业我认为是考核继承与多态,我认为只要学了继承与多态去写这道题也不算难。继承与多态让这道题更加符合现实生活中的情况,也更容易扩展。

第一次大作业(这次大作业的第一次)

题目:

航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
说明文件:https://images.ptausercontent.com/499d204b-fcef-4610-a9ca-c8fbf5e346d9.pdf

设计与分析

分析;

对于这次大作业,我把题目读完之后,第一想法就是不像第一次大作业(上一次大作业)那样有那么强的逻辑性,不再需要搞清楚什么时候停,什么时候上,什么时候下,什么时候开门。我觉得这次大作业把输入和输出弄好就差不多了,唯一需要捋一下的地方就是体积重量和实际重量在计算费率时到底用哪个的问题,至于其他的符合面向对象的设计原则就差不多了。

设计

我把输入样例看完之后,类的设计大概想法就有了个雏形。设计客户类、货物类、航班类、订单类和输出类。我认为这是看到输入和输出很容易就可以想出来的,但是我现在看来我觉得我这样划分或许还是范围大了些,或许还可以把订单类划分的更加细致,将其分为订单类,发件人类和收件人类。

代码查看

点击查看代码
import java.util.Scanner;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.*;

//客户类
class Customer{
    private String cust_num;    //编号
    private String name;
    private String phone_num;          //电话号码
    private String cust_address;
    private int transport_num;
    public Customer(String cust_num,String name,String phone_num,String cust_address,int transport_num){
        this.cust_num=cust_num;
        this.name=name;
        this.phone_num=phone_num;
        this.cust_address=cust_address;
        this.transport_num=transport_num;
    }
    public String getCust_num(){
        return cust_num;
    }
    public String getName(){
        return name;
    }
    public String getPhone_num(){
        return phone_num;
    }
    public String getCust_address(){
        return cust_address;
    }
    public int getTransport_num(){
        return transport_num;
    }
}

//货物类
class Goods{
    private int goods_num;
    private String goods_name;
    private double goods_width;
    private double goods_length;
    private double goods_height;
    private double goods_weight;
    public Goods(int goods_num,String goods_name,double goods_width,double goods_length,double goods_height,double goods_weight){
        this.goods_num=goods_num;
        this.goods_name=goods_name;
        this.goods_width=goods_width;
        this.goods_length=goods_length;
        this.goods_height=goods_height;
        this.goods_weight=goods_weight;
    }
    public int getGoods_num(){
        return goods_num;
    }
    public String getGoods_name(){
        return goods_name;
    }
    public double getGoods_width(){
        return goods_width;
    }
    public double getGoods_length(){
        return goods_length;
    }
    public double getGoods_height(){
        return goods_height;
    }
    public double getGoods_weight(){
        return goods_weight;
    }
    public double getVolumetricWeight() {     //体积重量
        return (goods_length * goods_width * goods_height) / 6000.0;
    }

    public double getChargeableWeight() {             //计算重量
        return Math.max(goods_weight, getVolumetricWeight());
    }
}

//航班类
class Flight{
    private String flight_num;
    private String flight_up;
    private String flight_down;
    private LocalDate flightDate;
    private double maxweight;
    public Flight(String flight_num,String flight_up,String flight_down,LocalDate flightDate,double maxweight){
        this.flight_num=flight_num;
        this.flight_up=flight_up;
        this.flight_down=flight_down;
        this.flightDate=flightDate;
        this.maxweight=maxweight;
    }
    public String getFlight_num(){
        return flight_num;
    }
    public String getFlight_up(){
        return flight_up;
    }
    public String getFlight_down(){
        return flight_down;
    }
    public LocalDate getFlightDate(){
        return flightDate;
    }
    public double getMaxweight(){
        return maxweight;
    }
}

//订单类
class Order{
    private int order_num;
    private LocalDate orderDate;
    private String sender_address;
    private String sender_name;
    private String sender_num;
    private String recipient_address;
    private String recipient_name;
    private String recipient_num;
    private List<Goods> goodsList;
    public Order(int order_num,LocalDate orderDate,String sender_address,String sender_name,String sender_num,String recipient_address,String recipient_name,String recipient_num, List<Goods> goodsList){
        this.order_num=order_num;
        this.orderDate=orderDate;
        this.sender_address=sender_address;
        this.sender_name=sender_name;
        this.sender_num=sender_num;
        this.recipient_address=recipient_address;
        this.recipient_name=recipient_name;
        this.recipient_num=recipient_num;
        this.goodsList = goodsList;
    }
    public int getOrder_num(){
        return order_num;
    }
    public LocalDate getOrderDate(){
        return orderDate;
    }
    public String getSender_address(){
        return sender_address;
    }
    public String getSender_name(){
        return sender_name;
    }
    public String getSender_num(){
        return sender_num;
    }
    public String getRecipient_address(){
        return recipient_address;
    }
    public String getRecipient_name(){
        return recipient_name;
    }
    public String getRecipient_num(){
        return recipient_num;
    }
    public List<Goods> getGoodsList() {
        return goodsList; 
    }
    public double calculateTotalFee() {
        double totalFee = 0.0;
        for (Goods goods : goodsList) {
        double chargeableWeight = goods.getChargeableWeight();
        double rate = getRateByWeight(chargeableWeight);
        totalFee += chargeableWeight * rate;
        }
        return totalFee;
    }

    public double getRateByWeight(double weight) {
        if (weight < 20.0) return 35.0;
        else if (weight < 50.0) return 30.0;
        else if (weight < 100.0) return 25.0;
        else return 15.0;
    }
}

class Show {
    public void display(Customer customer, Flight flight, Order order) {
        double totalWeight = calculateTotalWeight(order.getGoodsList());
        double totalFee = order.calculateTotalFee();
        System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getName(), customer.getPhone_num());
        System.out.println("-----------------------------------------");
        System.out.printf("航班号:%s\n", flight.getFlight_num());
        System.out.printf("订单号:%d\n", order.getOrder_num());
        System.out.println("订单日期:" + flight.getFlightDate());
        System.out.printf("发件人姓名:%s\n", order.getSender_name());
        System.out.printf("发件人电话:%s\n", order.getSender_num());
        System.out.printf("发件人地址:%s\n", order.getSender_address());
        System.out.printf("收件人姓名:%s\n", order.getRecipient_name());
        System.out.printf("收件人电话:%s\n", order.getRecipient_num());
        System.out.printf("收件人地址:%s\n", order.getRecipient_address());
        System.out.printf("订单总重量(kg):%.1f\n", totalWeight);
        System.out.printf("微信支付金额:%.1f\n", totalFee);
        System.out.println();
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        int i=1;
        for (Goods goods : order.getGoodsList()) {
            double chargeableWeight = goods.getChargeableWeight();
            double rate = order.getRateByWeight(chargeableWeight);
            double fee = chargeableWeight * rate;
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i++, goods.getGoods_name(), chargeableWeight, rate, fee);
        }
    }

    public double calculateTotalWeight(List<Goods> goodsList) {
        double totalWeight = 0.0;
        for (Goods goods : goodsList) {
            totalWeight += goods.getChargeableWeight();
        }
        return totalWeight;
    }
}

public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        //客户属性
        String cust_num=input.nextLine();
        String name=input.nextLine();
        String phone_num=input.nextLine();
        String cust_address=input.nextLine();
        int transport_num=input.nextInt();
        input.nextLine();
        Customer customer=new Customer(cust_num, name, phone_num, cust_address, transport_num);
        //货物属性
        List<Goods> goodsList = new ArrayList<>();
        for (int i = 0; i < transport_num; i++) {
            int goods_num = input.nextInt();
            input.nextLine();
            String goods_name = input.nextLine();
            double goods_width = input.nextDouble();
            double goods_length = input.nextDouble();
            double goods_height = input.nextDouble();
            double goods_weight = input.nextDouble();
            input.nextLine();
            goodsList.add(new Goods(goods_num, goods_name, goods_width, goods_length, goods_height, goods_weight));
        }
        //航班属性
        String flight_num=input.nextLine();
        String flight_up=input.nextLine();
        String flight_down=input.nextLine();
        LocalDate flightDate = LocalDate.parse(input.nextLine());
        double maxweight=input.nextDouble();
        Flight flight=new Flight(flight_num, flight_up, flight_down, flightDate, maxweight);
        //订单属性
        int order_num=input.nextInt();
        input.nextLine();
        LocalDate orderDate = LocalDate.parse(input.nextLine());
        String sender_address=input.nextLine();
        String sender_name=input.nextLine();
        String sender_num=input.nextLine();
        String recipient_address=input.nextLine();
        String recipient_name=input.nextLine();
        String recipient_num=input.nextLine();
        Order order=new Order(order_num, orderDate, sender_address, sender_name, sender_num, recipient_address, recipient_name, recipient_num, goodsList);
        Show show = new Show();
        double sumWeight = show.calculateTotalWeight(order.getGoodsList());
        if(sumWeight>flight.getMaxweight()){
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.",flight.getFlight_num());
            input.close();
            return;
        }
        else{
        show.display(customer, flight, order);
        input.close();
        }
    }
}

设计类图

image

代码分析

image
image
image
image
image
image

分析结果

项目概况:

代码规模: 267行,196个语句

类与接口数量: 6个

平均每个类的方法数: 6.00

平均每个方法的语句数: 3.47

代码质量指标

注释率

带注释的行百分比: 3.0% (偏低)

建议增加注释,特别是对复杂逻辑和关键方法的解释,提高代码可维护性。

分支语句

分支语句百分比: 5.1% (适中)

表明代码中条件逻辑比例合理,没有过度复杂的分支结构。

方法调用

方法调用语句: 37个

显示代码有一定的模块化和复用性。

复杂度分析

整体复杂度

最大复杂度: 5 (位于Order.getRateByWeight()方法)

平均复杂度: 1.28 (非常好)

平均块深度: 1.70

最大块深度: 3

块深度分布

0级深度: 10语句

1级深度: 61语句

2级深度: 103语句

3级深度: 22语句

4+级深度: 0语句

分布显示大多数代码(约83%)处于0-2级嵌套深度,结构良好。

最复杂方法

Order.getRateByWeight(): 复杂度5 (位于第166行)

这是代码中最复杂的方法,可能需要重构简化。

Main.main(): 复杂度4,40语句,3级深度,19次调用

主方法较长,考虑将部分逻辑分解到辅助方法中。

Show.display(): 复杂度2,15语句,3级深度,14次调用

显示逻辑较复杂,可考虑拆分。

类与方法分析:

典型类结构

大多数类(如Customer、Flight、Goods)包含:

1个构造函数(复杂度1)

多个getter方法(复杂度均为1)

方法平均语句数: 1-6个

这种结构简单清晰,符合良好设计原则。

值得关注的方法

Order.calculateTotalFee(): 复杂度2,6语句

Show.calculateTotalWeight(): 复杂度2,4语句

Goods.getChargeableWeight(): 包含1次方法调用

潜在问题

  1. 注释不足风险
    当前注释率仅3%,远低于行业推荐的10-20%标准

可能导致:新成员理解代码困难、长期维护成本增加、关键业务逻辑误解

特别风险点:复杂方法如Order.getRateByWeight()缺乏解释

  1. 复杂方法隐患
    Order.getRateByWeight() (复杂度5):

可能包含多重嵌套条件判断或循环

容易引入边界条件错误

单元测试难以覆盖所有路径

Main.main() (40语句):

违反单一职责原则

修改风险高,可能引发连锁反应

  1. 深度耦合迹象
    Main.main()调用19次其他方法

Show.display()调用14次其他方法

潜在问题:

牵一发而动全身的修改影响

难以独立测试和复用组件

系统扩展性受限

  1. 数据类设计缺陷
    多个类(Customer/Flight/Goods等)只有简单getter/setter:

贫血模型问题,业务逻辑可能分散在其他类中

数据与行为分离导致内聚性降低

例如运费计算逻辑可能没有放在合适的领域对象中

  1. 重量计算相关风险
    Goods.getChargeableWeight()有方法调用(其他getter都是0):

可能存在隐藏的业务规则依赖

如果计算逻辑变更可能影响多处

Order.calculateTotalFee()和重量计算相关:

与重量计算方法的耦合关系不明确

费率计算规则变更可能引发问题

  1. 可测试性问题
    高度耦合的Main类:

难以进行单元测试

可能需要大量mock对象

多个1语句的getter方法:

虽然简单但数量众多

测试维护成本可能被低估

改进建议

1、增加注释: 将注释率提升到10-20%,特别是对复杂方法如getRateByWeight()添加详细说明。

2、重构复杂方法:

分解Order.getRateByWeight()方法

拆分Main.main()的长方法

3、考虑使用设计模式:

对于包含多个getter/setter的类,考虑是否可以使用Builder模式

对于显示逻辑,考虑使用MVC模式分离

4、异常处理:

报告中未显示异常处理情况,建议检查关键操作是否有适当的错误处理

5、单元测试:

特别是针对复杂度较高的方法,应编写充分的测试用例

第二次大作业(这次大作业的第二次)

题目变化:

1、货物类型分为普通货物、危险货物和加急货物三种
2、用户分为个人用户和集团用户,其中个人用户可享受订单运费的9折优惠,集团用户可享受订单运费的8折优惠
3、费率根据货物类型的变化而变化
4、支付方式分为支付宝支付、微信支付、现金支付
具体详细请见:https://images.ptausercontent.com/b9cec79b-8012-4901-843e-3d48f27d28a6.pdf

设计与分析

由于货物和用户的划分变得更加细致,我们可以考虑采用继承与多态的方法来迭代这次程序。
我们可以将用户类变成抽象类,再创建个人用户类和集团用户类继承用户类,将折扣方法写成抽象类放在用户类里面,至于折扣的具体实现则在不同用户类里面单独实现。
货物类和用户类类似,将货物类写成抽象类,再写三个不同的货物继承货物类,至于不同费率的计算则在不同货物类里面单独实现。
至于支付方法,我的想法是单独写一个支付类,当输入的支付类名字为Wechat时则输出微信支付,其他支付同理。其实还有一个更加符合面向对象设计原则的一个设计方法,就是设计一个支付抽象类,根据不同的输入来创建不同的支付类,不过我当时并没有想到。

设计类图

image

代码查看

点击查看代码
import java.util.Scanner;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.*;

//客户类
abstract class Customer{
    private String cust_num;    //编号
    private String name;
    private String phone_num;          //电话号码
    private String cust_address;
    private int transport_num;
    public Customer(String cust_num,String name,String phone_num,String cust_address,int transport_num){
        this.cust_num=cust_num;
        this.name=name;
        this.phone_num=phone_num;
        this.cust_address=cust_address;
        this.transport_num=transport_num;
    }
    public String getCust_num(){
        return cust_num;
    }
    public String getName(){
        return name;
    }
    public String getPhone_num(){
        return phone_num;
    }
    public String getCust_address(){
        return cust_address;
    }
    public int getTransport_num(){
        return transport_num;
    }
    public abstract double Discount(double totalFee);
}

class Individual extends Customer{
    public Individual(String cust_num,String name,String phone_num,String cust_address,int transport_num){
        super(cust_num, name, phone_num, cust_address, transport_num);
    }
    public double Discount(double totalFee){
        return totalFee*0.9;
    }
}

class Corporate extends Customer{
    public Corporate(String cust_num,String name,String phone_num,String cust_address,int transport_num){
        super(cust_num, name, phone_num, cust_address, transport_num);
    }
    public double Discount(double totalFee){
        return totalFee*0.8;
    }
}

//货物类
abstract class Goods{
    private int goods_num;
    private String goods_name;
    private double goods_width;
    private double goods_length;
    private double goods_height;
    private double goods_weight;
    public Goods(int goods_num,String goods_name,double goods_width,double goods_length,double goods_height,double goods_weight){
        this.goods_num=goods_num;
        this.goods_name=goods_name;
        this.goods_width=goods_width;
        this.goods_length=goods_length;
        this.goods_height=goods_height;
        this.goods_weight=goods_weight;
    }
    public int getGoods_num(){
        return goods_num;
    }
    public String getGoods_name(){
        return goods_name;
    }
    public double getGoods_width(){
        return goods_width;
    }
    public double getGoods_length(){
        return goods_length;
    }
    public double getGoods_height(){
        return goods_height;
    }
    public double getGoods_weight(){
        return goods_weight;
    }
    public double getVolumetricWeight() {     //体积重量
        return (goods_length * goods_width * goods_height) / 6000.0;
    }

    public double getChargeableWeight() {             //计算重量
        return Math.max(goods_weight, getVolumetricWeight());
    }

    public abstract double getRateByWeight(double weight);
}

class Normal extends Goods{
    public Normal(int goods_num,String goods_name,double goods_width,double goods_length,double goods_height,double goods_weight){
        super(goods_num,goods_name,goods_width,goods_length,goods_height,goods_weight);
    }
    public double getRateByWeight(double weight){
        if (weight < 20.0) return 35.0;
        else if (weight < 50.0) return 30.0;
        else if (weight < 100.0) return 25.0;
        else return 15.0;
    }
}

class Expedite extends Goods{
    public Expedite(int goods_num,String goods_name,double goods_width,double goods_length,double goods_height,double goods_weight){
        super(goods_num,goods_name,goods_width,goods_length,goods_height,goods_weight);
    }
    public double getRateByWeight(double weight){
        if (weight < 20.0) return 60.0;
        else if (weight < 50.0) return 50.0;
        else if (weight < 100.0) return 40.0;
        else return 30.0;
    }
}

class Dangerous extends Goods{
    public Dangerous(int goods_num,String goods_name,double goods_width,double goods_length,double goods_height,double goods_weight){
        super(goods_num,goods_name,goods_width,goods_length,goods_height,goods_weight);
    }
    public double getRateByWeight(double weight){
        if (weight < 20.0) return 80.0;
        else if (weight < 50.0) return 50.0;
        else if (weight < 100.0) return 30.0;
        else return 20.0;
    }
}

//航班类
class Flight{
    private String flight_num;
    private String flight_up;
    private String flight_down;
    private LocalDate flightDate;
    private double maxweight;
    public Flight(String flight_num,String flight_up,String flight_down,LocalDate flightDate,double maxweight){
        this.flight_num=flight_num;
        this.flight_up=flight_up;
        this.flight_down=flight_down;
        this.flightDate=flightDate;
        this.maxweight=maxweight;
    }
    public String getFlight_num(){
        return flight_num;
    }
    public String getFlight_up(){
        return flight_up;
    }
    public String getFlight_down(){
        return flight_down;
    }
    public LocalDate getFlightDate(){
        return flightDate;
    }
    public double getMaxweight(){
        return maxweight;
    }
}

//订单类
class Order{
    private int order_num;
    private LocalDate orderDate;
    private String sender_address;
    private String sender_name;
    private String sender_num;
    private String recipient_address;
    private String recipient_name;
    private String recipient_num;
    private List<Goods> goodsList;
    public Order(int order_num,LocalDate orderDate,String sender_address,String sender_name,String sender_num,String recipient_address,String recipient_name,String recipient_num, List<Goods> goodsList){
        this.order_num=order_num;
        this.orderDate=orderDate;
        this.sender_address=sender_address;
        this.sender_name=sender_name;
        this.sender_num=sender_num;
        this.recipient_address=recipient_address;
        this.recipient_name=recipient_name;
        this.recipient_num=recipient_num;
        this.goodsList = goodsList;
    }
    public int getOrder_num(){
        return order_num;
    }
    public LocalDate getOrderDate(){
        return orderDate;
    }
    public String getSender_address(){
        return sender_address;
    }
    public String getSender_name(){
        return sender_name;
    }
    public String getSender_num(){
        return sender_num;
    }
    public String getRecipient_address(){
        return recipient_address;
    }
    public String getRecipient_name(){
        return recipient_name;
    }
    public String getRecipient_num(){
        return recipient_num;
    }
    public List<Goods> getGoodsList() {
        return goodsList; 
    }
    
    public double calculateTotalFee() {        //计算折扣前价钱
        double totalFee = 0.0;
        for (Goods goods : goodsList) {
        double chargeableWeight = goods.getChargeableWeight();
        double rate = goods.getRateByWeight(chargeableWeight);
        totalFee += chargeableWeight * rate;
        }
        return totalFee;
    }
}

class PayType{
    private String name;
    public PayType(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void show(){
        if(name.equals("Wechat")){
            System.out.printf("微信支付金额:");
        }else if(name.equals("ALiPay")){
            System.out.printf("支付宝支付金额:");
        }else{
            System.out.printf("现金支付金额:");
        }
    }
}

class Show {
    public void display(Customer customer, Flight flight, Order order,PayType payType) {
        double totalWeight = calculateTotalWeight(order.getGoodsList());
        double totalFee = order.calculateTotalFee();
        double disCountFee=customer.Discount(totalFee);
        System.out.printf("客户:%s(%s)订单信息如下:\n", customer.getName(), customer.getPhone_num());
        System.out.println("-----------------------------------------");
        System.out.printf("航班号:%s\n", flight.getFlight_num());
        System.out.printf("订单号:%d\n", order.getOrder_num());
        System.out.println("订单日期:" + flight.getFlightDate());
        System.out.printf("发件人姓名:%s\n", order.getSender_name());
        System.out.printf("发件人电话:%s\n", order.getSender_num());
        System.out.printf("发件人地址:%s\n", order.getSender_address());
        System.out.printf("收件人姓名:%s\n", order.getRecipient_name());
        System.out.printf("收件人电话:%s\n", order.getRecipient_num());
        System.out.printf("收件人地址:%s\n", order.getRecipient_address());
        System.out.printf("订单总重量(kg):%.1f\n", totalWeight);
        payType.show();
        System.out.printf("%.1f\n", disCountFee);
        System.out.println();
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        int i=1;
        for (Goods goods : order.getGoodsList()) {
            double chargeableWeight = goods.getChargeableWeight();
            double rate = goods.getRateByWeight(chargeableWeight);
            double fee = chargeableWeight * rate;
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n", i++, goods.getGoods_name(), chargeableWeight, rate, fee);
        }
    }

    public double calculateTotalWeight(List<Goods> goodsList) {
        double totalWeight = 0.0;
        for (Goods goods : goodsList) {
            totalWeight += goods.getChargeableWeight();
        }
        return totalWeight;
    }
}

public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        //客户属性
        String customerType = input.nextLine();
        String cust_num=input.nextLine();
        String name=input.nextLine();
        String phone_num=input.nextLine();
        String cust_address=input.nextLine();
        String goodsType = input.nextLine();
        int transport_num=input.nextInt();
        input.nextLine();
        Customer customer = null;
        if (customerType.equals("Individual")) {
            customer = new Individual(cust_num, name, phone_num, cust_address, transport_num);
        } else {
            customer = new Corporate(cust_num, name, phone_num, cust_address, transport_num);
        }
        //货物属性
        List<Goods> goodsList = new ArrayList<>();
        for (int i = 0; i < transport_num; i++) {
            int goods_num = input.nextInt();
            input.nextLine();
            String goods_name = input.nextLine();
            double goods_width = input.nextDouble();
            double goods_length = input.nextDouble();
            double goods_height = input.nextDouble();
            double goods_weight = input.nextDouble();
            input.nextLine();
            Goods goods=null;
            if (goodsType.equals("Normal")) {
                goods = new Normal(goods_num, goods_name, goods_width, goods_length, goods_height, goods_weight);
            } else if (goodsType.equals("Expedite")) {
                goods = new Expedite(goods_num, goods_name, goods_width, goods_length, goods_height, goods_weight);
            } else{
                goods = new Dangerous(goods_num, goods_name, goods_width, goods_length, goods_height, goods_weight);
            }
            goodsList.add(goods);
        }
        //航班属性
        String flight_num=input.nextLine();
        String flight_up=input.nextLine();
        String flight_down=input.nextLine();
        LocalDate flightDate = LocalDate.parse(input.nextLine());
        double maxweight=input.nextDouble();
        Flight flight=new Flight(flight_num, flight_up, flight_down, flightDate, maxweight);
        //订单属性
        int order_num=input.nextInt();
        input.nextLine();
        LocalDate orderDate = LocalDate.parse(input.nextLine());
        String sender_address=input.nextLine();
        String sender_name=input.nextLine();
        String sender_num=input.nextLine();
        String recipient_address=input.nextLine();
        String recipient_name=input.nextLine();
        String recipient_num=input.nextLine();
        //支付方法
        String payType_name=input.nextLine();
        PayType payType=new PayType(payType_name);
        Order order=new Order(order_num, orderDate, sender_address, sender_name, sender_num, recipient_address, recipient_name, recipient_num, goodsList);
        Show show = new Show();
        double sumWeight = show.calculateTotalWeight(order.getGoodsList());
        if(sumWeight>flight.getMaxweight()){
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.",flight.getFlight_num());
            input.close();
            return;
        }
        else{
        show.display(customer, flight, order, payType);
        input.close();
        }
    }
}

代码分析

image
image
image
image

分析结果

项目概况:

代码规模:361行代码,255条语句

注释率:仅3.9%的行有注释,低于一般推荐值(15-20%)

类结构:8个类和接口,每个类平均6个方法

方法复杂度:平均每个方法5.1条语句

复杂度分析

均复杂度:2.44(较好,一般建议保持在5以下)

最复杂方法:Main.main()复杂度高达9,包含55条语句,块深度4

其他较复杂方法:多个getRateByWeight()方法复杂度为5

块深度分析

最大块深度:4(在Main.main()方法中)

平均块深度:1.29(较好)

块深度分布:

深度0:71语句

深度1:71语句

深度2:84语句

潜在问题

Main.main()方法过于复杂:

复杂度9(接近建议上限10)

包含55条语句(建议不超过20-30条)

块深度达到4

需要重构,可能拆分为多个小方法

注释不足:

仅3.9%的行有注释,可能影响代码可维护性

重复模式:

多个类有相似的getRateByWeight()方法(复杂度5),考虑使用继承或策略模式减少重复

改进建议

重构Main.main()方法,将其逻辑分解到多个辅助方法中

增加代码注释,特别是复杂逻辑部分

考虑对getRateByWeight()等相似方法进行抽象重构

虽然平均复杂度良好,但需关注那几个复杂度5的方法

整体来看,代码结构尚可,但存在几个明显的高复杂度热点需要优化,特别是主方法过于臃肿的问题。

踩坑心得

认知心得

起初认为抽象类里面就必须全得是子类必须完成的抽象方法,但是这两次大作业让我了解到对于getter和setter这类子类和父类都有的相同方法,只需写在父类完成就行,而子类只需要继承就行,对于父类的public方法,子类是可以直接使用的,而对于父类的private属性,子类也可以通过get间接访问。

写题状态心得

写题时需要注意题目给的边界条件,而且对于涉及计算的程序,大部分测试点估计都是边界测试和正常测试,不注意边界测试会让程序在运行特殊值时会出现BUG

总结

这两次大作业使我对面向对象的程序设计原则体会更深,不像面向过程的程序设计,面向对象的程序设计更加符合现实运转的规律,而且面向对象的程序设计更容易扩展和迭代,使得代码更加灵活和易于维护。