Minecraft风格博客加载动画
MINEBLOG
0%
正在加载资源...

欢迎来到 content 2024 博客

你好(*´▽`)ノノ

题目集8~9的“航空货运管理系统”题目总结

题目集8~9的“航空货运管理系统”题目总结

目录

  • 前言
  • 设计与分析
  • 采坑心得
  • 自身改进
  • 总结

前言

在本次java课程的题目集8~9中,我们深入研究了航空货运管理系统问题。通过这一系列的练习,对继承与多态JAVA中的不断学习,以及不断增加新的功能,我学到了很多:

  1. 熟悉了继承与多态的运用;
  2. 深入构建面向对象的设计思路;
  3. 继承与多态的认识及其进一步的了解;
  4. SourceMonitor代码分析软件的使用学习及其应用;
  5. 认识到了代码可拓展性的重要;

Complexity Metrics(复杂度分析)

因为下面要用到复杂度分析,所以先在此给出一些相关概念。
我们需要使用的主要是方法和类的复杂度分析。
方法的复杂度分析主要基于循环复杂度的计算。循环复杂度是一种表示程序复杂度的软件度量,由程序流程图中的“基础路径”数量得来。

  1. ev(G):即Essentail Complexity,用来表示一个方法的结构化程度,范围在[1,v(G)]​之间,值越大则程序的结构越“病态”,其计算过程和图的“缩点”有关。
  2. iv(G):即Design Complexity,用来表示一个方法和他所调用的其他方法的紧密程度,范围也在[1,v(G)]​之间,值越大联系越紧密
  3. v(G):即循环复杂度,可以理解为穷尽程序流程每一条路径所需要的试验次数。
    时间复杂度(Time Complexity)
  • 描述算法执行所需时间的增长率。通常以大O符号表示,反映算法在最坏情况下的效率。常见的时间复杂度包括:
    O(1):常数时间
    O(log n):对数时间(例如,二分查找)
    O(n):线性时间(例如,遍历一个数组)
    O(n log n):线性对数时间(例如,归并排序)
    O(n²):平方时间(例如,冒泡排序)
    空间复杂度(Space Complexity)

  • 衡量算法执行时所需内存的增长率。也使用大O符号表示。它包括:
    固定空间:算法运行时固定占用的空间
    可变空间:依赖于问题规模的输入而变化的空间

(和上次差不多,进行了一些修正(`・ω・´))

设计与分析

第一题题目描述

本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
√ 客户信息(姓名,电话号码等)
√ 货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
√ 运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选航班号,订单日期)
√ 支付方式(支付宝支付、微信支付)

  • 注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独计费。
  • 程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表
输入输出样例
输入样例:
在这里给出一组输入。例如:

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

题目分析

题目要求模拟一个客户到航空公司办理货运业务的过程, 具体功能需求包括:

  • 输入客户信息:客户编号、姓名、电话、地址。
  • 输入货物信息:每件货物的编号、名称、宽度、长度、高度、重量。
  • 输入航班信息:航班号、起飞机场、降落机场、航班日期、最大载重量。
  • 输入订单信息:订单编号、订单日期、发件人信息(地址、姓名、电话)、收件人信息(地址、姓名、电话)。
  • 计算货物总重量:根据货物的体积和实际重量,选择较大的值作为计费重量。
  • 判断是否超载:如果货物总重量超过航班最大载重量,输出超载信息并终止程序。
  • 输出订单信息和货物明细:如果未超载,输出完整的订单信息和货物明细。

关键点

1.数据结构设计:

  • 使用类来封装不同的实体,如 User(客户)、Goods(货物)、Flight(航班)、List(订单)、Sender(发件人)、Recipient(收件人)。
  • 使用数组或集合来管理多件货物。

2.计费规则:

  • 货物的计费重量为体积重量(长×宽×高 / 6000)和实际重量的较大值。
    根据货物重量范围计算运费。

3.输入输出格式:

  • 输入格式严格按题目要求,注意日期格式的解析。
  • 输出格式要求清晰,实型数保留一位小数。

设计与实现

类设计

1. User 类

1.功能:存储客户信息。

2.属性:

  • number:客户编号(String)
  • name:客户姓名(String)
  • CallNumber:客户电话号码(String)
  • Place:客户地址(String)

3.方法:

  • setNumber(String number):设置客户编号
  • setName(String name):设置客户姓名
  • setCallNumber(String callNumber):设置客户电话号码
  • setPlace(String place):设置客户地址
  • getNumber():获取客户编号
  • getName():获取客户姓名
  • getCallNumber():获取客户电话号码
  • getPlace():获取客户地址

2. Goods 类

1.功能:存储货物信息并计算相关费用。

2.属性:

  • number:货物编号(int)
  • name:货物名称(String)
  • Length:货物长度(double)
  • width:货物宽度(double)
  • height:货物高度(double)
  • weight:货物实际重量(double)
  • pair:货物运费(double)
  • numRate:货物计费费率(double)

3.方法:

  • setNumber(int number):设置货物编号
  • setName(String name):设置货物名称
  • setWidth(double width):设置货物宽度
  • setLength(double length):设置货物长度
  • setHeight(double height):设置货物高度
  • setWeight(double weight):设置货物实际重量
  • SumWeight():计算货物的计费重量(体积重量和实际重量的较大值)
  • SumPair():计算货物运费
  • getNumRate():获取货物计费费率
  • getPair():获取货物运费

3. Flight 类

1.功能:存储航班信息。

2.属性:

  • number:航班号(String)
  • upPlace:起飞机场所在城市(String)
  • downPlace:降落机场所在城市(String)
  • flightTimeH:航班日期(年)(int)
  • flightTimeM:航班日期(月)(int)
  • flightTimeD:航班日期(日)(int)
  • maxContent:航班最大载重量(double)

3.方法:

  • setNumber(String number):设置航班号
  • setUpPlace(String upPlace):设置起飞机场
  • setDownPlace(String downPlace):设置降落机场
  • setFlightTimeH(int flightTimeH):设置航班日期(年)
  • setFlightTimeM(int flightTimeM):设置航班日期(月)
  • setFlightTimeD(int flightTimeD):设置航班日期(日)
  • setMaxContent(double maxContent):设置航班最大载重量
  • getNumber():获取航班号
  • getUpPlace():获取起飞机场
  • getDownPlace():获取降落机场
  • getFlightTimeH():获取航班日期(年)
  • getFlightTimeM():获取航班日期(月)
  • getFlightTimeD():获取航班日期(日)
  • getMaxContent():获取航班最大载重量

4. List 类

1.功能:存储订单信息。

2.属性:

  • listNumber:订单编号(String)
  • listTimeH:订单日期(年)(int)
  • listTimeM:订单日期(月)(int)
  • listTimeD:订单日期(日)(int)

3.方法:

  • setListNumber(String listNumber):设置订单编号
  • setListTimeH(int listTimeH):设置订单日期(年)
  • setListTimeM(int listTimeM):设置订单日期(月)
  • setListTimeD(int listTimeD):设置订单日期(日)
  • getListNumber():获取订单编号
  • getListTimeH():获取订单日期(年)
  • getListTimeM():获取订单日期(月)
  • getListTimeD():获取订单日期(日)

5. Sender 类

1.功能:存储发件人信息。

2.属性:

  • place:发件人地址(String)
  • name:发件人姓名(String)
  • callNumber:发件人电话号码(String)

3.方法:

  • setPlace(String place):设置发件人地址
  • setName(String name):设置发件人姓名
  • setCallNumber(String callNumber):设置发件人电话号码
  • getPlace():获取发件人地址
  • getName():获取发件人姓名
  • getCallNumber():获取发件人电话号码

6. Recipient 类

1.功能:存储收件人信息。

2.属性:

  • place:收件人地址(String)
  • name:收件人姓名(String)
  • callNumber:收件人电话号码(String)

3.方法:

  • setPlace(String place):设置收件人地址
  • setName(String name):设置收件人姓名
  • setCallNumber(String callNumber):设置收件人电话号码
  • getPlace():获取收件人地址
  • getName():获取收件人姓名
  • getCallNumber():获取收件人电话号码

7. Rate 类

1.功能:根据货物重量计算运费和计费费率。

2.方法:

  • SumPair(double weight):根据货物重量计算运费
  • NameRate(double weight):根据货物重量返回计费费率

8. Control 类

1.功能:输出订单信息和货物明细。

2.方法:

  • Show(User user, Flight flight, Sender sender, Goods[] goods, List list, Recipient recipient, double weight, double pair):输出订单信息和货物明细

9. Main 类

1.功能:主程序入口,负责从键盘读取输入并调用其他类的方法。

2.逻辑:

  • 读取客户信息。
  • 读取货物信息。
  • 读取航班信息。
  • 读取订单信息。
  • 计算货物总重量。
  • 判断是否超载。
  • 如果超载,输出超载信息并终止程序。
  • 如果未超载,调用 Control 类的 Show 方法输出订单信息和货物明细。

核心逻辑

1.读取输入信息:

  • 客户信息
  • 货物信息
  • 航班信息
  • 订单信息
  • 发件人和收件人信息

2.计算货物总重量和运费:

  • 每件货物的计费重量为体积重量(长×宽×高 / 6000)和实际重量的较大值。
  • 根据货物重量范围计算运费。
  • 判断是否超载。
  • 如果货物总重量超过航班最大载重量,输出超载信息并终止程序。

3.输出订单信息和货物明细:

  • 如果未超载,输出完整的订单信息和货物明细。

以下是源码

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

public class Main {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        User user = new User();
        user.setNumber(scanner.nextLine());
        user.setName(scanner.nextLine());
        user.setCallNumber(scanner.nextLine());
        user.setPlace(scanner.nextLine());
        int MaxContent = scanner.nextInt();
        int content = 0;
        double weight = 0;
        double pair = 0;
        Goods[] goods = new Goods[MaxContent];
        String interim;
        while(content<MaxContent) {
            String NewInterim = scanner.nextLine();
            if (content < MaxContent) {
                goods[content] = new Goods();
                goods[content].setNumber(scanner.nextInt());
                scanner.nextLine(); // 消耗掉换行符
                goods[content].setName(scanner.nextLine());
                goods[content].setWitghth(scanner.nextDouble());
                goods[content].setLength(scanner.nextDouble());
                goods[content].setHeight(scanner.nextDouble());
                goods[content].setWeight(scanner.nextDouble());
                weight += goods[content].SumWeight();
                goods[content].SumPair();
                pair += goods[content].getPair();
                content++;
            }
        }
        scanner.nextLine();
        interim = scanner.nextLine();
        Flight flight = new Flight();
        flight.setNumber(interim);
        flight.setUpPlace(scanner.nextLine());
        flight.setDownPlace(scanner.nextLine());
        interim = scanner.nextLine();
        Pattern pattern = Pattern.compile("\\d+-+\\d+-+\\d+");
        Matcher matcher = pattern.matcher(interim);
        if(matcher.find()){
            String[] dateParts = matcher.group(0).split("-");
            flight.setFlightTimeH(Integer.parseInt(dateParts[0]));
            flight.setFlightTimeM(Integer.parseInt(dateParts[1]));
            flight.setFlightTimeD(Integer.parseInt(dateParts[2]));
        }
        while (!scanner.hasNextDouble()) {
            scanner.nextLine(); // 消耗掉无效的输入
        }
        flight.setMaxContent(scanner.nextDouble());
        scanner.nextLine();
        List list =new List();
        list.setListNumber(scanner.nextLine());
        interim = scanner.nextLine();
        pattern = Pattern.compile("\\d+-+\\d+-+\\d+");
        matcher = pattern.matcher(interim);
        if(matcher.find()){
            String[] dateParts = matcher.group(0).split("-");
            list.setListTimeH(Integer.parseInt(dateParts[0]));
            list.setListTimeM(Integer.parseInt(dateParts[1]));
            list.setListTimeD(Integer.parseInt(dateParts[2]));
        }
        Sender sender = new Sender();
        sender.setPlace(scanner.nextLine());
        sender.setName(scanner.nextLine());
        sender.setCallNUmber(scanner.nextLine());
        Recipient recipient = new Recipient();
        recipient.setPlace(scanner.nextLine());
        recipient.setName(scanner.nextLine());
        recipient.setCallNUmber(scanner.nextLine());
        if(weight>flight.getMaxContent()){
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flight.getNumber());
            return;
        }
        Control control = new Control();
        control.Show(user,flight,sender,goods,list,recipient,weight,pair);
    }
}
class Control {
    public void Show(User user,Flight flight,Sender sender,Goods[] goods,List list,Recipient recipient,double weight,double pair){
        System.out.println("客户:"+user.getName()+"("+user.getCallNumber()+")"+"订单信息如下:");
        System.out.println("-----------------------------------------");
        System.out.println("航班号:"+flight.getNumber());
        System.out.println("订单号:"+list.getListNumber());
        System.out.printf("订单日期:%04d-%02d-%02d\n",list.getListTimeH(),list.getListTimeM(),list.getListTimeD());
        System.out.println("发件人姓名:"+sender.getName());
        System.out.println("发件人电话:"+sender.getCallNUmber());
        System.out.println("发件人地址:"+sender.getPlace());
        System.out.println("收件人姓名:"+recipient.getName());
        System.out.println("收件人电话:"+recipient.getCallNUmber());
        System.out.println("收件人地址:"+recipient.getPlace());
        System.out.println("订单总重量(kg):"+ weight);
        System.out.println("微信支付金额:"+ pair + "\n");
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for(int i=0;i<goods.length;i++){
            System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n",i+1,goods[i].getName(),goods[i].SumWeight(),goods[i].getNumRate(),goods[i].getPair());
        }
    }
}
class Flight {
    private String Number;
    private String UpPlace;
    private String DownPlace;
    private int FlightTimeH;
    private int FlightTimeM;
    private int FlightTimeD;
    private double MaxContent;
    public String getNumber() {
        return Number;
    }

    public void setNumber(String number) {
        Number = number;
    }

    public int getFlightTimeD() {
        return FlightTimeD;
    }

    public void setFlightTimeD(int flightTimeD) {
        FlightTimeD = flightTimeD;
    }

    public int getFlightTimeH() {
        return FlightTimeH;
    }

    public void setFlightTimeH(int flightTimeH) {
        FlightTimeH = flightTimeH;
    }

    public int getFlightTimeM() {
        return FlightTimeM;
    }

    public void setFlightTimeM(int flightTimeM) {
        FlightTimeM = flightTimeM;
    }

    public String getDownPlace() {
        return DownPlace;
    }

    public void setDownPlace(String downPlace) {
        DownPlace = downPlace;
    }

    public String getUpPlace() {
        return UpPlace;
    }

    public void setUpPlace(String upPlace) {
        UpPlace = upPlace;
    }

    public double getMaxContent() {
        return MaxContent;
    }

    public void setMaxContent(double maxContent) {
        this.MaxContent = maxContent;
    }
}
class Goods {
    Rate rate =new Rate();
    private int Number;
    private String name;
    private double Length;
    private double witghth;
    private double height;
    private double weight;
    private double pair;
    private double numRate;
    public double getPair() {
        return pair;
    }

    public void setPair(double pair) {
        this.pair = pair;
    }

    public String getName() {
        return name;
    }

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

    public double getHeight() {
        return height;
    }

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

    public double getLength() {
        return Length;
    }

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

    public double getWeight() {
        return weight;
    }

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

    public double getWitghth() {
        return witghth;
    }

    public void setWitghth(double witghth) {
        this.witghth = witghth;
    }

    public int getNumber() {
        return Number;
    }

    public void setNumber(int number) {
        Number = number;
    }

    public double SumWeight(){
        double TpWeight = (this.Length*this.witghth*this.height)/6000;
        return TpWeight>weight ? TpWeight : weight;
    }

    public void SumPair(){
        this.pair = rate.SumPair(SumWeight());
        this.numRate = rate.NameRate(SumWeight());
    }

    public double getNumRate() {
        return numRate;
    }

    public void setNumRate(double numRate) {
        this.numRate = numRate;
    }
}
class List {
    private String ListNumber;
    private int ListTimeH;
    private int ListTimeM;
    private int ListTimeD;

    public String getListNumber() {
        return ListNumber;
    }

    public void setListNumber(String listNumber) {
        this.ListNumber = listNumber;
    }

    public int getListTimeD() {
        return ListTimeD;
    }

    public void setListTimeD(int listTimeD) {
        ListTimeD = listTimeD;
    }

    public int getListTimeH() {
        return ListTimeH;
    }

    public void setListTimeH(int listTimeH) {
        ListTimeH = listTimeH;
    }

    public int getListTimeM() {
        return ListTimeM;
    }

    public void setListTimeM(int listTimeM) {
        ListTimeM = listTimeM;
    }
}
class Rate {
    public double SumPair(double weight){
        double pair = 0;
        if(weight<20) {
            pair = weight * 35;
        } else if(weight<50){
            pair = weight * 30;
        } else if (weight<100) {
            pair = weight * 25;
        } else {
            pair = weight * 15;
        }
        return pair;
    }
    public double NameRate(double weight){
        if(weight<20) {
            return 35;
        } else if(weight<50){
            return 30;
        } else if (weight<100) {
            return 25;
        } else {
            return 15;
        }
    }
}
class Recipient {
    private String place;
    private String name;
    private String CallNUmber;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getName() {
        return name;
    }

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

    public String getCallNUmber() {
        return CallNUmber;
    }

    public void setCallNUmber(String callNUmber) {
        CallNUmber = callNUmber;
    }
}
class Sender {
    private String place;
    private String name;
    private String CallNUmber;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getName() {
        return name;
    }

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

    public String getCallNUmber() {
        return CallNUmber;
    }

    public void setCallNUmber(String callNUmber) {
        CallNUmber = callNUmber;
    }
}
class User {
    private String number;
    private String name;
    private String CallNumber;
    private String Place;

    public String getName() {
        return name;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCallNumber() {
        return CallNumber;
    }

    public void setCallNumber(String callNumber) {
        CallNumber = callNumber;
    }

    public String getPlace() {
        return Place;
    }

    public void setPlace(String place) {
        Place = place;
    }
}

Source Monitor分析结果:

点此处看方法具体复杂度
Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\Codes\Codes\src\plane\
Project Name				PlanePay_8
Checkpoint Name				Baseline
File Name				Main.java
Lines					85
Statements				73
Percent Branch Statements		8.2
Method Call Statements			48
Percent Lines with Comments		2.4
Classes and Interfaces			1
Methods per Class			1.00
Average Statements per Method		67.00
Line Number of Most Complex Method	8
Name of Most Complex Method		Main.main()
Maximum Complexity			7
Line Number of Deepest Block		24
Maximum Block Depth			4
Average Block Depth			2.67
Average Complexity			7.00

--------------------------------------------------------------------------------------------
Most Complex Methods in 1 Class(es):	Complexity, Statements, Max Depth, Calls

Main.main()				7, 67, 4, 48

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					5
1					1
2					24
3					26
4					17
5					0
6					0
7					0
8					0
9+					0
--------------------------------------------------------------------------------------------

分析与心得

代码存在的主要问题:

  • 代码复杂度较高:
    • 问题描述:
      (1)平均复杂度:Average Complexity 为 7.00,远高于推荐的复杂度(通常建议不超过 3-5)。
      (2)最复杂方法:Main.main() 方法的复杂度为 7,包含 67 条语句,最大嵌套深度为 4。
    • 原因分析:
      (1)单一职责原则未遵循:Main.main() 方法承担了过多的职责,包括读取输入、处理逻辑和输出结果。 这导致方法体过长,逻辑复杂。
      (2)嵌套层次深:代码中存在多层嵌套的 if-else 和循环结构,增加了代码的复杂度。
  • 代码注释量过少:
    • 问题描述:
      (1)注释比例:Percent Lines with Comments 仅为 2.4%,说明代码中几乎没有注释。
    • 原因分析:
      (1)缺乏注释习惯:在编写代码时,没有养成添加注释的习惯,只关注代码的功能实现。
  • 代码可读性差:
    • 问题描述:
      (1)方法过长:Main.main() 方法包含 67 条语句,过长的方法难以理解和维护。
      (2)嵌套深度高:最大嵌套深度为 4,增加了代码的复杂度和阅读难度。

第二题题目描述

本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
√ 客户信息(姓名,电话号码等)
√ 货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
√ 运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选航班号,订单日期)
√ 支付方式(支付宝支付、微信支付、现金支付)

  • 注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独计费。
  • 程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表

题目分析

该题的计费方式和之前的不同:
(1)新增客户类型[Individual/Corporate]

其中,每个类型的客户拥有不同的折扣率,折扣率是指不同的用户类型针对每个订单的运费可以享受相应的折扣,
在本题中,用户分为个人用户和集团用户,其中个人用户可享受订单运费的9折优惠,集团用户可享受订单运费的8折优惠。

(2)新增货物类型[Normal/Expedite/Dangerous]

其中,不同类型的货物拥有不同的费率:

(3)新增支付类型[Wechat/ALiPay/Cash]

关键点

1.数据结构设计:

  • 使用类来封装不同的实体,如 User(客户)、Goods(货物)、Flight(航班)、List(订单)、Sender(发件人)、Recipient(收件人)。
  • 使用数组或集合来管理多件货物。

2.计费规则:

  • 货物的计费重量为体积重量(长×宽×高 / 6000)和实际重量的较大值。
    根据货物重量范围计算运费。

3.输入输出格式:

  • 输入格式严格按题目要求,注意日期格式的解析。
  • 输出格式要求清晰,实型数保留一位小数。

4.用户类型的判断:

  • 在User中,新建一个String类型type,引入判断用户的类型;
  • 在User中,新建一个int类型date,标记用户类型。

5.货物类型的判断

6.支付类型的判断

设计与实现

类设计

1. User 类

1.功能:存储客户信息。

2.属性:

  • number:客户编号(String)
  • name:客户姓名(String)
  • CallNumber:客户电话号码(String)
  • Place:客户地址(String)
  • type:用户类型(String)
  • date:用户类型状态(int)

3.方法:

  • setNumber(String number):设置客户编号
  • setName(String name):设置客户姓名
  • setCallNumber(String callNumber):设置客户电话号码
  • setPlace(String place):设置客户地址
  • getNumber():获取客户编号
  • getName():获取客户姓名
  • getCallNumber():获取客户电话号码
  • getPlace():获取客户地址
  • setType(String type):设置用户类型并根据类型设置用户类型状态
  • getDate():获取用户类型状态

2. Goods 类

1.功能:存储货物信息并计算相关费用。

2.属性:

  • number:货物编号(int)
  • name:货物名称(String)
  • Length:货物长度(double)
  • width:货物宽度(double)
  • height:货物高度(double)
  • weight:货物实际重量(double)
  • pair:货物运费(double)
  • numRate:货物计费费率(double)
  • type:货物类型(String)
  • date:货物类型状态(int)

3.方法:

  • setNumber(int number):设置货物编号
  • setName(String name):设置货物名称
  • setWidth(double width):设置货物宽度
  • setLength(double length):设置货物长度
  • setHeight(double height):设置货物高度
  • setWeight(double weight):设置货物实际重量
  • setType(String type):设置货物类型并根据类型货物类型状态
  • SumWeight():计算货物的计费重量(体积重量和实际重量的较大值)
  • SumPair():计算货物运费
  • getNumRate():获取货物计费费率
  • getPair():获取货物运费

3. Flight 类

1.功能:存储航班信息。

2.属性:

  • number:航班号(String)
  • upPlace:起飞机场所在城市(String)
  • downPlace:降落机场所在城市(String)
  • flightTimeH:航班日期(年)(int)
  • flightTimeM:航班日期(月)(int)
  • flightTimeD:航班日期(日)(int)
  • maxContent:航班最大载重量(double)

3.方法:

  • setNumber(String number):设置航班号
  • setUpPlace(String upPlace):设置起飞机场
  • setDownPlace(String downPlace):设置降落机场
  • setFlightTimeH(int flightTimeH):设置航班日期(年)
  • setFlightTimeM(int flightTimeM):设置航班日期(月)
  • setFlightTimeD(int flightTimeD):设置航班日期(日)
  • setMaxContent(double maxContent):设置航班最大载重量
  • getNumber():获取航班号
  • getUpPlace():获取起飞机场
  • getDownPlace():获取降落机场
  • getFlightTimeH():获取航班日期(年)
  • getFlightTimeM():获取航班日期(月)
  • getFlightTimeD():获取航班日期(日)
  • getMaxContent():获取航班最大载重量

4. List 类

1.功能:存储订单信息。

2.属性:

  • listNumber:订单编号(String)
  • listTimeH:订单日期(年)(int)
  • listTimeM:订单日期(月)(int)
  • listTimeD:订单日期(日)(int)

3.方法:

  • setListNumber(String listNumber):设置订单编号
  • setListTimeH(int listTimeH):设置订单日期(年)
  • setListTimeM(int listTimeM):设置订单日期(月)
  • setListTimeD(int listTimeD):设置订单日期(日)
  • getListNumber():获取订单编号
  • getListTimeH():获取订单日期(年)
  • getListTimeM():获取订单日期(月)
  • getListTimeD():获取订单日期(日)

5. Sender 类

1.功能:存储发件人信息。

2.属性:

  • place:发件人地址(String)
  • name:发件人姓名(String)
  • callNumber:发件人电话号码(String)

3.方法:

  • setPlace(String place):设置发件人地址
  • setName(String name):设置发件人姓名
  • setCallNumber(String callNumber):设置发件人电话号码
  • getPlace():获取发件人地址
  • getName():获取发件人姓名
  • getCallNumber():获取发件人电话号码

6. Recipient 类

1.功能:存储收件人信息。

2.属性:

  • place:收件人地址(String)
  • name:收件人姓名(String)
  • callNumber:收件人电话号码(String)

3.方法:

  • setPlace(String place):设置收件人地址
  • setName(String name):设置收件人姓名
  • setCallNumber(String callNumber):设置收件人电话号码
  • getPlace():获取收件人地址
  • getName():获取收件人姓名
  • getCallNumber():获取收件人电话号码

7. Rate 类

1.功能:根据货物重量计算运费和计费费率。

2.方法:

  • SumPair(double weight, int date):根据货物重量和货物类型计算运费
  • NameRate(double weight, int date):根据货物重量和货物类型返回计费费率

8. Control 类

1.功能:输出订单信息和货物明细。

2.方法:

  • Show(User user, Flight flight, Sender sender, Goods[] goods, List list, Recipient recipient, double weight, double pair, Payment payment):输出订单信息和货物明细

9. Payment 类

1.职责:存储支付信息。

2.属性:

  • payerName:支付人姓名(String)
  • amount:支付金额类型(int)

3.方法:

  • setPayerName(String payerName):设置支付人姓名并根据姓名设置支付金额类型
  • getAmount():获取支付金额类型
  • getPayerName():获取支付人姓名

10. Main 类

1.功能:主程序入口,负责从键盘读取输入并调用其他类的方法。

2.逻辑:

  • 读取客户信息。
  • 读取货物信息。
  • 读取航班信息。
  • 读取订单信息。
  • 计算货物总重量。
  • 判断是否超载。
  • 如果超载,输出超载信息并终止程序。
  • 如果未超载,调用 Control 类的 Show 方法输出订单信息和货物明细。

核心逻辑

1.读取输入信息:

  • 客户信息
  • 货物信息
  • 航班信息
  • 订单信息
  • 发件人和收件人信息

2.计算货物总重量和运费:

  • 每件货物的计费重量为体积重量(长×宽×高 / 6000)和实际重量的较大值。
  • 根据货物重量范围计算运费。
  • 判断是否超载。
  • 如果货物总重量超过航班最大载重量,输出超载信息并终止程序。

3.输出订单信息和货物明细:

  • 如果未超载,输出完整的订单信息和货物明细。

以下是源码

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

public class Main {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        User user = new User();
        user.setType(scanner.nextLine());
        user.setNumber(scanner.nextLine());
        user.setName(scanner.nextLine());
        user.setCallNumber(scanner.nextLine());
        user.setPlace(scanner.nextLine());
        String NewInterim = scanner.nextLine();
        int MaxContent = scanner.nextInt();
        int content = 0;
        double weight = 0;
        double pair = 0;
        Goods[] goods = new Goods[MaxContent];
        String interim;
        while(content<MaxContent) {
            if (content < MaxContent) {
                goods[content] = new Goods();
                scanner.nextLine();
                goods[content].setType(NewInterim);
                goods[content].setNumber(scanner.nextInt());
                scanner.nextLine(); // 消耗掉换行符
                goods[content].setName(scanner.nextLine());
                goods[content].setWitghth(scanner.nextDouble());
                goods[content].setLength(scanner.nextDouble());
                goods[content].setHeight(scanner.nextDouble());
                goods[content].setWeight(scanner.nextDouble());
                weight += goods[content].SumWeight();
                goods[content].SumPair();
                pair += goods[content].getPair();
                content++;
            }
        }
        scanner.nextLine();
        interim = scanner.nextLine();
        Flight flight = new Flight();
        flight.setNumber(interim);
        flight.setUpPlace(scanner.nextLine());
        flight.setDownPlace(scanner.nextLine());
        interim = scanner.nextLine();
        Pattern pattern = Pattern.compile("\\d+-+\\d+-+\\d+");
        Matcher matcher = pattern.matcher(interim);
        if(matcher.find()){
            String[] dateParts = matcher.group(0).split("-");
            flight.setFlightTimeH(Integer.parseInt(dateParts[0]));
            flight.setFlightTimeM(Integer.parseInt(dateParts[1]));
            flight.setFlightTimeD(Integer.parseInt(dateParts[2]));
        }
        while (!scanner.hasNextDouble()) {
            scanner.nextLine(); // 消耗掉无效的输入
        }
        flight.setMaxContent(scanner.nextDouble());
        scanner.nextLine();
        List list =new List();
        list.setListNumber(scanner.nextLine());
        interim = scanner.nextLine();
        pattern = Pattern.compile("\\d+-+\\d+-+\\d+");
        matcher = pattern.matcher(interim);
        if(matcher.find()){
            String[] dateParts = matcher.group(0).split("-");
            list.setListTimeH(Integer.parseInt(dateParts[0]));
            list.setListTimeM(Integer.parseInt(dateParts[1]));
            list.setListTimeD(Integer.parseInt(dateParts[2]));
        }
        Sender sender = new Sender();
        sender.setPlace(scanner.nextLine());
        sender.setName(scanner.nextLine());
        sender.setCallNUmber(scanner.nextLine());
        Recipient recipient = new Recipient();
        recipient.setPlace(scanner.nextLine());
        recipient.setName(scanner.nextLine());
        recipient.setCallNUmber(scanner.nextLine());
        if(weight>flight.getMaxContent()){
            System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flight.getNumber());
            return;
        }
        Control control = new Control();
        Payment payment = new Payment();
        payment.setPayerName(scanner.nextLine());
        control.Show(user,flight,sender,goods,list,recipient,weight,pair,payment);
    }
}
class Control {
    public void Show(User user,Flight flight,Sender sender,Goods[] goods,List list,Recipient recipient,double weight,double pair,Payment payment){
        System.out.println("客户:"+user.getName()+"("+user.getCallNumber()+")"+"订单信息如下:");
        System.out.println("-----------------------------------------");
        System.out.println("航班号:"+flight.getNumber());
        System.out.println("订单号:"+list.getListNumber());
        System.out.printf("订单日期:%04d-%02d-%02d\n",list.getListTimeH(),list.getListTimeM(),list.getListTimeD());
        System.out.println("发件人姓名:"+sender.getName());
        System.out.println("发件人电话:"+sender.getCallNUmber());
        System.out.println("发件人地址:"+sender.getPlace());
        System.out.println("收件人姓名:"+recipient.getName());
        System.out.println("收件人电话:"+recipient.getCallNUmber());
        System.out.println("收件人地址:"+recipient.getPlace());
        System.out.println("订单总重量(kg):"+ weight);
        if(user.getDate()==1){
            if(payment.getAmount()==1)
                System.out.println("微信支付金额:"+ pair*0.9 + "\n");
            if(payment.getAmount()==2)
                System.out.println("支付宝支付金额:"+ pair*0.9 + "\n");
            if(payment.getAmount()==3){
                System.out.println("现金支付金额:"+ pair*0.9 + "\n");
            }
        }
        else{
            if(payment.getAmount()==1)
                System.out.println("微信支付金额:"+ pair*0.8 + "\n");
            if(payment.getAmount()==2)
                System.out.println("支付宝支付金额:"+ pair*0.8 + "\n");
            if(payment.getAmount()==3){
                System.out.println("现金支付金额:"+ pair*0.8 + "\n");
            }
        }
        System.out.println("货物明细如下:");
        System.out.println("-----------------------------------------");
        System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
        for(int i=0;i<goods.length;i++){
            if(user.getDate()==1)
                System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n",i+1,goods[i].getName(),goods[i].SumWeight(),goods[i].getNumRate(),goods[i].getPair());
            else
                System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f\n",i+1,goods[i].getName(),goods[i].SumWeight(),goods[i].getNumRate(),goods[i].getPair());
        }
    }
}
class Flight {
    private String Number;
    private String UpPlace;
    private String DownPlace;
    private int FlightTimeH;
    private int FlightTimeM;
    private int FlightTimeD;
    private double MaxContent;
    public String getNumber() {
        return Number;
    }

    public void setNumber(String number) {
        Number = number;
    }

    public int getFlightTimeD() {
        return FlightTimeD;
    }

    public void setFlightTimeD(int flightTimeD) {
        FlightTimeD = flightTimeD;
    }

    public int getFlightTimeH() {
        return FlightTimeH;
    }

    public void setFlightTimeH(int flightTimeH) {
        FlightTimeH = flightTimeH;
    }

    public int getFlightTimeM() {
        return FlightTimeM;
    }

    public void setFlightTimeM(int flightTimeM) {
        FlightTimeM = flightTimeM;
    }

    public String getDownPlace() {
        return DownPlace;
    }

    public void setDownPlace(String downPlace) {
        DownPlace = downPlace;
    }

    public String getUpPlace() {
        return UpPlace;
    }

    public void setUpPlace(String upPlace) {
        UpPlace = upPlace;
    }

    public double getMaxContent() {
        return MaxContent;
    }

    public void setMaxContent(double maxContent) {
        this.MaxContent = maxContent;
    }
}
class Goods {
    Rate rate =new Rate();
    private int Number;
    private String name;
    private double Length;
    private double witghth;
    private double height;
    private double weight;
    private double pair;
    private double numRate;
    private String type;
    private int date;

    public int getDate() {
        return date;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
        if("Normal".equals(type)){
            date=1;
        }
        if("Expedite".equals(type)){
            date=2;
        }
        if("Dangerous".equals(type)){
            date=3;
        }
    }

    public double getPair() {
        return pair;
    }

    public void setPair(double pair) {
        this.pair = pair;
    }

    public String getName() {
        return name;
    }

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

    public double getHeight() {
        return height;
    }

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

    public double getLength() {
        return Length;
    }

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

    public double getWeight() {
        return weight;
    }

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

    public double getWitghth() {
        return witghth;
    }

    public void setWitghth(double witghth) {
        this.witghth = witghth;
    }

    public int getNumber() {
        return Number;
    }

    public void setNumber(int number) {
        Number = number;
    }

    public double SumWeight(){
        double TpWeight = (this.Length*this.witghth*this.height)/6000;
        return TpWeight>weight ? TpWeight : weight;
    }

    public void SumPair(){
        this.pair = rate.SumPair(SumWeight(),date);
        this.numRate = rate.NameRate(SumWeight(),date);
    }

    public double getNumRate() {
        return numRate;
    }

    public void setNumRate(double numRate) {
        this.numRate = numRate;
    }
}
class List {
    private String ListNumber;
    private int ListTimeH;
    private int ListTimeM;
    private int ListTimeD;

    public String getListNumber() {
        return ListNumber;
    }

    public void setListNumber(String listNumber) {
        this.ListNumber = listNumber;
    }

    public int getListTimeD() {
        return ListTimeD;
    }

    public void setListTimeD(int listTimeD) {
        ListTimeD = listTimeD;
    }

    public int getListTimeH() {
        return ListTimeH;
    }

    public void setListTimeH(int listTimeH) {
        ListTimeH = listTimeH;
    }

    public int getListTimeM() {
        return ListTimeM;
    }

    public void setListTimeM(int listTimeM) {
        ListTimeM = listTimeM;
    }
}
class Rate {
    public double SumPair(double weight,int date){
        double pair = 0;
        if(weight<20) {
            if(date==1)
                pair = weight * 35;
            if(date==2)
                pair = weight * 60;
            if(date==3)
                pair = weight * 80;
        } else if(weight<50){
            if(date==1)
                pair = weight * 30;
            if(date==2)
                pair = weight * 50;
            if(date==3)
                pair = weight * 50;
        } else if (weight<100) {
            if(date==1)
                pair = weight * 25;
            if(date==2)
                pair = weight * 40;
            if(date==3)
                pair = weight * 30;
        } else {
            if(date==1)
                pair = weight * 15;
            if(date==2)
                pair = weight * 30;
            if(date==3)
                pair = weight * 20;
        }
        return pair;
    }
    public double NameRate(double weight,int date){
        if(weight<20) {
            if(date==1)
                return 35;
            if(date==2)
                return 60;
            if(date==3)
                return 80;
        } else if(weight<50){
            if(date==1)
                return 30;
            if(date==2)
                return 50;
            if(date==3)
                return 50;
        } else if (weight<100) {
            if(date==1)
                return 25;
            if(date==2)
                return 40;
            if(date==3)
                return 30;
        } else {
            if(date==1)
                return 15;
            if(date==2)
                return 30;
            if(date==3)
                return 20;
        }
        return 0;
    }
}
class Recipient {
    private String place;
    private String name;
    private String CallNUmber;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getName() {
        return name;
    }

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

    public String getCallNUmber() {
        return CallNUmber;
    }

    public void setCallNUmber(String callNUmber) {
        CallNUmber = callNUmber;
    }
}
class Payment {
    private String payerName;
    private int amount;

    public int getAmount() {
        return amount;
    }

    public String getPayerName() {
        return payerName;
    }

    public void setPayerName(String payerName) {
        this.payerName = payerName;
        if("Wechat".equals(payerName)){
            this.amount = 1;
        }
        if("ALiPay".equals(payerName)){
            this.amount = 2;
        }
        if("Cash".equals(payerName)){
            this.amount = 3;
        }
    }
}
class Sender {
    private String place;
    private String name;
    private String CallNUmber;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getName() {
        return name;
    }

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

    public String getCallNUmber() {
        return CallNUmber;
    }

    public void setCallNUmber(String callNUmber) {
        CallNUmber = callNUmber;
    }
}
class User {
    private String number;
    private String name;
    private String CallNumber;
    private String Place;
    private String type;
    private int date;

    public int getDate() {
        return date;
    }

    public void setType(String type) {
        this.type = type;
        if ("Individual".equals(type)) {
            date = 1;
        } else {
            date = 2;
        }
    }

    public String getName() {
        return name;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCallNumber() {
        return CallNumber;
    }

    public void setCallNumber(String callNumber) {
        CallNumber = callNumber;
    }

    public String getPlace() {
        return Place;
    }

    public void setPlace(String place) {
        Place = place;
    }
}

Source Monitor分析结果:

点此处看方法具体复杂度
Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\Codes\Codes\src\plane1\
Project Name				PlanePay_9
Checkpoint Name				Baseline
File Name				Main.java
Lines					90
Statements				78
Percent Branch Statements		7.7
Method Call Statements			51
Percent Lines with Comments		2.2
Classes and Interfaces			1
Methods per Class			1.00
Average Statements per Method		72.00
Line Number of Most Complex Method	8
Name of Most Complex Method		Main.main()
Maximum Complexity			7
Line Number of Deepest Block		25
Maximum Block Depth			4
Average Block Depth			2.69
Average Complexity			7.00

--------------------------------------------------------------------------------------------
Most Complex Methods in 1 Class(es):	Complexity, Statements, Max Depth, Calls

Main.main()				7, 72, 4, 51

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					5
1					1
2					26
3					27
4					19
5					0
6					0
7					0
8					0
9+					0
--------------------------------------------------------------------------------------------

分析与心得

代码存在的主要问题:

  • 代码复杂度较高:
    • 问题描述:
      (1)平均复杂度:Average Complexity 为 7.00,远高于推荐的复杂度(通常建议不超过 3-5)。
      (2)最复杂方法:Main.main() 方法的复杂度为 7,包含 67 条语句,最大嵌套深度为 4
    • 原因分析:
      (1)单一职责原则未遵循:Main.main() 方法承担了过多的职责,包括读取输入、处理逻辑和输出结果。 这导致方法体过长,逻辑复杂。
      (2)嵌套层次深:代码中存在多层嵌套的 if-else 和循环结构,增加了代码的复杂度。
  • 代码注释量过少:
    • 问题描述:
      (1)注释比例:Percent Lines with Comments 仅为 2.4%,说明代码中几乎没有注释。
    • 原因分析:
      (1)缺乏注释习惯:在编写代码时,没有养成添加注释的习惯,只关注代码的功能实现。
  • 代码可读性差:
    • 问题描述:
      (1)方法过长:Main.main() 方法包含 67 条语句,过长的方法难以理解和维护。
      (2)嵌套深度高:最大嵌套深度为 4,增加了代码的复杂度和阅读难度。

心得

通过这次代码分析,我深刻认识到代码设计的重要性。以下是我的一些心得:

  • 遵循单一职责原则:
    每个类和方法应该只负责一个功能,避免功能过于集中。这不仅可以降低代码复杂度,还能提高代码的可维护性。例如,将 Main.main() 方法拆分为多个小方法,每个方法只负责一个特定的功能。
  • 减少嵌套层次:
    通过使用早期返回、循环控制等技巧,减少嵌套层次,使代码更加清晰易读。例如,使用 if 语句的早期返回来避免深层嵌套。
  • 添加注释:
    在编写代码时,养成添加注释的习惯,尤其是在复杂的逻辑部分。注释不仅可以帮助其他开发者理解代码,也能在未来维护代码时提供帮助。
  • 优化算法结构:
    通过使用设计模式(如工厂模式、策略模式)来简化复杂的条件判断逻辑,提高代码的可读性和可维护性。
  • 提高代码可读性:
    使用清晰、一致的变量命名规范,避免使用过于简短或模糊的变量名。同时,尽量减少方法的长度,将长方法拆分为多个小方法。
  • 持续改进:
    代码设计是一个持续改进的过程。通过使用工具(如 SourceMonitor)来检查代码质量,及时发现并解决代码中的问题。

采坑心得

在完成这次编程任务的过程中,我遇到了不少问题,也积累了一些宝贵的经验。
以下是我总结的采坑心得:

1. 代码复杂度过高

  • 问题描述
    • Main.main() 方法的复杂度达到了 7,包含 67 条语句,最大嵌套深度为 4。这使得代码难以理解和维护。
  • 问题原因
    • 单一职责原则未遵循Main.main() 方法承担了过多的职责,包括读取输入、处理逻辑和输出结果。这导致方法体过长,逻辑复杂。
    • 嵌套层次深:代码中存在多层嵌套的 if-else 和循环结构,增加了代码的复杂度。
  • 解决方法
    • 拆分方法:将 Main.main() 方法拆分为多个小方法,每个方法只负责一个特定的功能。例如:
      • readUserInput(Scanner scanner):读取用户输入。
      • processGoods(Scanner scanner):处理货物信息。
      • checkWeight(Goods[] goods, Flight flight):检查货物总重量是否超载。
      • printOrderDetails(User user, Flight flight, Sender sender, Goods[] goods, List list, Recipient recipient, double weight, double pair, Payment payment):输出订单信息。
    • 简化逻辑:通过使用设计模式(如工厂模式、策略模式)来简化复杂的条件判断逻辑。
    • 减少嵌套:尽量减少嵌套层次,使用早期返回(early return)等技巧来降低嵌套深度。

2. 代码注释量过少

  • 问题描述
    • Percent Lines with Comments 仅为 2.4%,说明代码中几乎没有注释。
  • 问题原因
    • 缺乏注释习惯:在编写代码时,没有养成添加注释的习惯,只关注代码的功能实现。
  • 解决方法
    • 添加关键逻辑注释:在复杂的逻辑部分添加详细的注释,说明代码的作用和实现思路。
    • 类和方法注释:为每个类和方法添加注释,说明它们的功能、输入输出参数等。
    • 统一命名规范:使用清晰、一致的变量命名规范,避免使用过于简短或模糊的变量名。

3. 代码可读性差

  • 问题描述
    • Main.main() 方法包含 67 条语句,过长的方法难以理解和维护。
    • 最大嵌套深度为 4,增加了代码的复杂度和阅读难度。
  • 问题原因
    • 方法过长Main.main() 方法承担了过多的职责,导致方法体过长。
    • 嵌套层次深:代码中存在多层嵌套的 if-else 和循环结构,增加了代码的复杂度。
  • 解决方法
    • 拆分方法:将长方法拆分为多个小方法,每个方法只负责一个特定的功能。
    • 减少嵌套:通过使用早期返回、循环控制等技巧减少嵌套层次。
    • 使用集合类:使用 ArrayListLinkedList 等集合类来管理动态数据,而不是使用固定大小的数组。

4. 输入处理问题

  • 问题描述
    • 在处理输入时,没有对输入数据进行充分的验证和处理,导致程序在某些情况下可能会抛出异常或运行结果不符合预期。
  • 问题原因
    • 输入格式敏感:代码对输入格式的要求较为严格,例如日期格式必须为 YYYY-MM-DD,且某些字段必须大写(如 UPDOWN)。
    • 缺乏输入验证:对于无效的输入,如非数字字符、无效的楼层号等,代码没有进行充分的验证和处理。
  • 解决方法
    • 增加输入验证:在读取输入时,对输入数据进行验证,确保输入格式正确且有效。
    • 容错处理:对于无效的输入,提供友好的错误提示,并允许用户重新输入。
    • 使用正则表达式:使用正则表达式来验证输入格式,确保输入数据符合预期。

5. 逻辑错误

  • 问题描述
    • 在计算货物总重量和运费时,逻辑存在错误,导致计算结果不准确。
  • 问题原因
    • 逻辑不清晰:在计算货物总重量和运费时,逻辑较为复杂,容易出错。
    • 缺乏测试:没有对计算逻辑进行充分的测试,导致某些情况下计算结果不准确。
  • 解决方法
    • 简化逻辑:通过使用设计模式(如工厂模式、策略模式)来简化复杂的条件判断逻辑。
    • 增加测试:为计算逻辑编写单元测试,确保计算结果准确无误。
    • 代码复审:定期回顾和优化代码,确保逻辑正确无误。

总结

通过这次编程任务,我深刻认识到代码设计的重要性。以下是我的一些心得:

  1. 遵循单一职责原则:每个类和方法应该只负责一个功能,避免功能过于集中。这不仅可以降低代码复杂度,还能提高代码的可维护性。
  2. 减少嵌套层次:通过使用早期返回、循环控制等技巧,减少嵌套层次,使代码更加清晰易读。
  3. 添加注释:在编写代码时,养成添加注释的习惯,尤其是在复杂的逻辑部分。注释不仅可以帮助其他开发者理解代码,也能在未来维护代码时提供帮助。
  4. 优化算法结构:通过使用设计模式(如工厂模式、策略模式)来简化复杂的条件判断逻辑,提高代码的可读性和可维护性。
  5. 提高代码可读性:使用清晰、一致的变量命名规范,避免使用过于简短或模糊的变量名。同时,尽量减少方法的长度,将长方法拆分为多个小方法。
  6. 增加输入验证:在读取输入时,对输入数据进行验证,确保输入格式正确且有效。对于无效的输入,提供友好的错误提示,并允许用户重新输入。
  7. 持续改进:代码设计是一个持续改进的过程。通过使用工具(如 SourceMonitor)来检查代码质量,及时发现并解决代码中的问题。

建议

1. 建议课程针对迭代题目提供阶段性帮助

在每次的迭代题目结束后,为学生提供一些引导式的帮助,帮助他们在下一次题目集中找到正确的方向。同时,确保学生能够学习到正确的设计模式。

以这次题目为例,首次题暴露的核心痛点在于需求边界模糊——同学们对数据判断处理,类的划分等关键规则存在差异化解读,导致前期试错成本过高。在保证题目质量的基础上,可以尝试分阶段提供资源帮助:

  • 首轮作业完成后:发布基础核心逻辑。这样既保留了自主设计的空间,也能给予第一次没能完成题目集的同学一些信心,还能建立统一的认知基线。
  • 二次迭代后:给出经典设计模式解析,通过一些范例引导同学们关注扩展性设计。这样可以让同学们在完成下次迭代题目时,能够有目的性地去优化自己的代码结构。

这种递进式帮助体系既能缓解初期认知过载(不知道怎么下手),又能为后续复杂迭代奠定可延续的技术基础。

2. 建议迭代题目的分值应该递增设置

这样可以激励那些没做出来前一次迭代题目的同学更加重视起来。因为如果分值递减,有些同学可能会不愿意花时间在迭代题上,只追求前面的简单分值,从而无法得到编程能力的提升。

通过递增分值的设置,可以更好地激励学生逐步深入学习,不断提升自己的编程能力,而不是仅仅停留在表面。

posted on 2025-05-18 12:13  content2024  阅读(61)  评论(3)    收藏  举报

导航