第二次博客作业
一、前言
1. 题目背景
航空货运管理系统是一个模拟航空公司货运业务的系统,主要涉及运费计算和订单管理。运费计算基于货物重量/体积,并考虑货物类型、用户类型等影响因素。
2. 两次作业的共同点
| 考察点 | 第一次作业 | 第二次作业 |
|---|---|---|
| 运费计算方式 | 基于实际重量和体积重量取较大值 | 相同 |
| 计费公式 | 体积重量 = (长×宽×高) / 6000 |
相同 |
| 订单管理 | 客户填写订单,包含货物、运送、支付信息 | 相同 |
| 面向对象设计原则 | 单一职责、里氏替换、开闭原则、合成复用 | 新增依赖倒置原则 |
| 输出要求 | 生成订单信息报表和货物明细报表 | 相同 |
3. 第二次作业的新增要求
| 新增/调整内容 | 说明 |
|---|---|
| 费率计算方式 | 第一次采用分段计费(按重量区间),第二次改为基于货物类型(普通、危险、加急) |
| 用户折扣 | 新增个人用户(9折)和集团用户(8折) |
| 支付方式 | 第一次仅支持支付宝、微信支付,第二次新增现金支付 |
| 设计原则 | 第一次考察4个原则,第二次新增依赖倒置原则 |
| 可扩展性 | 明确提示用户、支付方式、货物需要可扩展 |
二:设计与分析:
1.第一次航空货运管理系统程序:
设计:
1.Main类 - 相当于系统的大脑,负责协调各个模块工作
2. Customer类 - 处理客户信息(姓名、电话、地址等)
3. Product类 - 管理货物信息和运费计算
4. Flight类 - 处理航班信息
5. Order类 - 管理订单信息
6. Payment相关类 - 处理支付方式(但我没做具体实现😢)
点击查看代码
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("#.0");
// 读取客户信息
int customerID = Integer.parseInt(sc.nextLine().trim());
String customerName = sc.nextLine().trim();
String customerPhone = sc.nextLine().trim();
String customerAddress = sc.nextLine().trim();
Customer customer = new Customer(customerID, customerName, customerPhone, customerAddress);
// 读取货物信息
int goodsNumber = Integer.parseInt(sc.nextLine().trim());
List<Product> products = new ArrayList<>();
double totalBillingWeight = 0;
for (int i = 0; i < goodsNumber; i++) {
int productID = Integer.parseInt(sc.nextLine().trim());
String productName = sc.nextLine().trim();
double width = Double.parseDouble(sc.nextLine().trim());
double length = Double.parseDouble(sc.nextLine().trim());
double height = Double.parseDouble(sc.nextLine().trim());
double weight = Double.parseDouble(sc.nextLine().trim());
Product product = new Product(i+1, productID, productName, weight, length, width, height);
double volumeWeight = product.calculateVolumeWeight(length, width, height);
double billingWeight = Math.max(weight, volumeWeight);
totalBillingWeight += billingWeight; // 累加计费重量
products.add(product);
}
// 读取航班信息
String flightID = sc.nextLine().trim();
String departureCity = sc.nextLine().trim();
String arrivalCity = sc.nextLine().trim();
String flightDate = sc.nextLine().trim();
double maxLoadWeight = Double.parseDouble(sc.nextLine().trim());
Flight flight = new Flight(flightID, departureCity, arrivalCity, flightDate, maxLoadWeight);
// 检查航班载重
if (totalBillingWeight > maxLoadWeight) {
System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flightID);
return;
}
// 读取订单信息
String orderID = sc.nextLine().trim();
String orderDate = sc.nextLine().trim();
String senderAddress = sc.nextLine().trim();
String senderName = sc.nextLine().trim();
String senderPhone = sc.nextLine().trim();
String receiverAddress = sc.nextLine().trim();
String receiverName = sc.nextLine().trim();
String receiverPhone = sc.nextLine().trim();
// 创建订单
Order order = new Order();
order.setOrderID(orderID);
order.setOrderDate(orderDate);
order.setSendername(senderName);
order. setSenderphonenumber(senderPhone);
order.setSenderaddress(senderAddress);
order.setReceivername(receiverName);
order.setReceiverphonenumber(receiverPhone);
order.setReceiveraddress(receiverAddress);
order.setFlightnumber(flight);
// 计算运费
double totalPayment = 0;
for (Product product : products) {
double volumeWeight = product.calculateVolumeWeight(product.getLength(), product.getWidth(), product.getHeight());
double billingWeight = Math.max(product.getWeight(), volumeWeight);
double freight = product.calculateFreight(billingWeight);
totalPayment += freight;
}
// 输出订单信息
System.out.println("客户:" + customerName + "(" + customerPhone + ")订单信息如下:");
System.out.println("-----------------------------------------");
System.out.println("航班号:" + flightID);
System.out.println("订单号:" + orderID);
System.out.println("订单日期:" + orderDate);
System.out.println("发件人姓名:" + senderName);
System.out.println("发件人电话:" + senderPhone);
System.out.println("发件人地址:" + senderAddress);
System.out.println("收件人姓名:" + receiverName);
System.out.println("收件人电话:" + receiverPhone);
System.out.println("收件人地址:" + receiverAddress);
System.out.println("订单总重量(kg):" + df.format(totalBillingWeight));
System.out.println("微信支付金额:" + df.format(totalPayment));
System.out.println();
System.out.println("货物明细如下:");
System.out.println("-----------------------------------------");
System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
for (Product product : products) {
double volumeWeight = product.calculateVolumeWeight(
product.getLength(),
product.getWidth(),
product.getHeight()
);
double billingWeight = Math.max(product.getWeight(), volumeWeight);
double freight = product.calculateFreight(billingWeight);
double rate = freight / billingWeight;
System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f%n",
product.getNumber(),
product.getProductName(),
billingWeight,
rate,
freight);
}
}
}
class Customer {
private int customerID;
private String customerName;
private String phonenumber;
private String address;
public Customer() {}
public Customer(int customerID, String customerName, String phonenumber, String address) {
this.customerID = customerID;
this.customerName = customerName;
this.phonenumber = phonenumber;
this.address = address;
}
public int getCustomerID() { return customerID; }
public String getName() { return customerName; }
public String getPhonenumber() { return phonenumber; }
public String getAddress() { return address; }
public void setCustomerID(int customerID) { this.customerID = customerID; }
public void setName(String name) { this.customerName = name; }
public void setPhonenumber(String phonenumber) { this.phonenumber = phonenumber; }
public void setAddress(String address) { this.address = address; }
}
class Product {
private int number;
private int productID;
private String productName;
private double weight;
private double length;
private double width;
private double height;
public Product() {
}
public Product(int number, int productID, String productName, double weight, double length, double width, double height) {
this.number = number;
this.productID = productID;
this.productName = productName;
this.weight = weight;
this.length = length;
this.width = width;
this.height = height;
}
public int getNumber() {
return number;
}
public int getProductID() {
return productID;
}
public String getProductName() {
return productName;
}
public double getWeight() {
return weight;
}
public double getLength() {
return length;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public void setNumber(int number) {
this.number = number;
}
public void setProductID(int productID) {
this.productID = productID;
}
public void setProductName(String productName) {
this.productName = productName;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void setLength(double length) {
this.length = length;
}
public void setWidth(double width) {
this.width = width;
}
public void setHeight(double height) {
this.height = height;
}
public double calculateVolumeWeight(double length, double width, double height) {
return (length * width * height)/6000.0;
}
public double calculateFreight(double billingWeight) {
int rate;
if (billingWeight < 20) {
rate = 35;
} else if (billingWeight < 50&&billingWeight >=20) {
rate = 30;
} else if (billingWeight >= 50&&billingWeight < 100) {
rate = 25;
} else {
rate = 15;
}
return rate * billingWeight;
}
}
class Flight {
private String flightID;
private String departureCity;
private String arrivalCity;
private String flightDate;
private double maxLoadWeight;
public Flight() {}
public Flight(String flightID, String departureCity, String arrivalCity, String flightDate, double maxLoadWeight){
this.flightID = flightID;
this.departureCity = departureCity;
this.arrivalCity = arrivalCity;
this.flightDate = flightDate;
this.maxLoadWeight = maxLoadWeight;
}
public String getFlightID() {return flightID;}
public String getDepartureCity() {return departureCity;}
public String getArrivalCity() {return arrivalCity;}
public String getFlightDate() {return flightDate;}
public double getMaxLoadWeight() {return maxLoadWeight;}
public void setFlightID(String flightID) {this.flightID = flightID;}
public void setDepartureCity(String departureCity) {this.departureCity = departureCity;}
public void setArrivalCity(String arrivalCity) {this.arrivalCity = arrivalCity;}
public void setFlightDate(String flightDate) {this.flightDate = flightDate;}
public void setMaxLoadWeight(double maxLoadWeight) {this.maxLoadWeight = maxLoadWeight;}
}
class Order {
private String orderID;
private String orderDate;
private String sendername;
private String senderphonenumber;
private String senderaddress;
private String receivername;
private String receiverphonenumber;
private String receiveraddress;
private Flight flightnumber;
public Order() {}
public String getOrderID() {return orderID;}
public void setOrderID(String orderID) {this.orderID = orderID;}
public String getOrderDate() {return orderDate;}
public void setOrderDate(String orderDate) {this.orderDate = orderDate;}
public String getSendername() {return sendername;}
public void setSendername(String sendername) {this.sendername = sendername;}
public String getSenderphonenumber() {return senderphonenumber;}
public void setSenderphonenumber(String senderphonenumber) {
this.senderphonenumber = senderphonenumber;
}
public void setFlightnumber(Flight flightnumber) {
this.flightnumber = flightnumber;
}
public Flight getFlightnumber() {return flightnumber;}
public String getSenderaddress() {return senderaddress;}
public void setSenderaddress(String senderaddress) {this.senderaddress = senderaddress;}
public String getReceivername() {return receivername;}
public void setReceivername(String receivername) {this.receivername = receivername;}
public String getReceiverphonenumber() {return receiverphonenumber;}
public void setReceiverphonenumber(String receiverphonenumber) {this.receiverphonenumber = receiverphonenumber;}
public String getReceiveraddress() {return receiveraddress;}
public void setReceiveraddress(String receiveraddress) {this.receiveraddress = receiveraddress;}
}
abstract class Payment {
public Payment(){}
public abstract void pay(double amount);
}
class WechatPayment extends Payment {
@Override
public void pay(double amount) {
}
}
class AliPayment extends Payment {
@Override
public void pay(double amount) {}
}
类图:

报表内容:

航空货运管理系统代码质量分析
一、核心问题分析
- 运费计算模块(Product.java)
public double calculateFreight() {
if (type == DANGEROUS) { // 分支1
if (weight > 50) { ... } // 分支2
else if (...) { ... } // 分支3
}
else if (type == EXPRESS) { // 分支4
// ...共7层条件嵌套
}
}
高复杂度问题
- 圈复杂度高达7(建议值<5)
- 包含7层条件嵌套
设计原则违反
- 违反单一职责原则(SRP)
- 违反开闭原则(OCP)
• 🚨 圈复杂度高达7(建议值<5)
• 🧩 违反单一职责原则(SRP)
• 🔄 新增货物类型需修改核心逻辑
二、质量指标评估
| 质量指标 | 当前值 | 推荐值 | 评估 |
|---|---|---|---|
| 方法语句数 | 30 | ≤15 | ⚠️ 超标 |
| 方法调用次数 | 60 | - | ⚠️ 过高 |
✔ 优势亮点
- 基础类(Order/Flight)设计规范
- 支付模块扩展性良好(OCP)
- 平均嵌套深度1.36(优于行业标准)
2.第二次航空货运管理系统程序
设计:
主要改进亮点
- 客户分级处理:现在系统能区分个人客户和集团客户了,个人打9折,集团打8折。这个用到了继承和抽象方法,Customer变成了抽象类,下面有IndividualCustomer和GroupCustomer两个子类。
- 货物类型区分:不再是统一费率,现在分成了普通货物、危险品和加急货物三种类型,每种费率不同。这里用了一个很聪明的策略模式(FreightStrategy),把运费计算规则封装成不同的策略类。
- 支付方式扩展:支付方式从两种增加到三种(微信、支付宝、现金),而且用接口(PaymentMethod)来定义支付行为,以后要加新的支付方式很方便。
具体实现分析 - 输入处理更灵活:
◦ 现在会先读取客户类型和货物类型,再创建对应的对象
◦ 用了Java 8的Stream API来计算总重量和总运费,代码更简洁 - 运费计算更专业:
◦ 每种货物类型有自己的计算策略(NormalStrategy/DangerousCargoStrategy/ExpediteStrategy)
◦ 策略类里实现了calculate和getRate两个方法,计算和查询费率分开 - 折扣处理更规范:
◦ 折扣逻辑放在Customer的子类里实现
◦ 调用applyDiscount方法自动应用对应折扣 - 报表生成更完整:
◦ 单独写了printReport方法处理输出
◦ 能正确显示不同支付方式的名称
◦ 货物明细表格格式统一
点击查看代码
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("#.0");
// 读取客户信息
String customerType = sc.nextLine().trim();
int customerID = Integer.parseInt(sc.nextLine().trim());
String customerName = sc.nextLine().trim();
String customerPhone = sc.nextLine().trim();
String customerAddress = sc.nextLine().trim();
Customer customer = customerType.equalsIgnoreCase("Individual") ?
new IndividualCustomer(customerID, customerName, customerPhone, customerAddress) :
new GroupCustomer(customerID, customerName, customerPhone, customerAddress);
// 读取货物信息
String cargoType = sc.nextLine().trim();
int goodsNumber = Integer.parseInt(sc.nextLine().trim());
List<Product> products = new ArrayList<>();
for (int i = 0; i < goodsNumber; i++) {
int productID = Integer.parseInt(sc.nextLine().trim());
String productName = sc.nextLine().trim();
double width = Double.parseDouble(sc.nextLine().trim());
double length = Double.parseDouble(sc.nextLine().trim());
double height = Double.parseDouble(sc.nextLine().trim());
double weight = Double.parseDouble(sc.nextLine().trim());
Product product = new Product(i+1, productID, productName, weight, length, width, height);
product.setCargoType(cargoType);
products.add(product);
}
// 计算总计费重量
double totalBillingWeight = products.stream()
.mapToDouble(p -> Math.max(p.getWeight(), p.calculateVolumeWeight()))
.sum();
// 读取航班信息
String flightID = sc.nextLine().trim();
String departureCity = sc.nextLine().trim();
String arrivalCity = sc.nextLine().trim();
String flightDate = sc.nextLine().trim();
double maxLoadWeight = Double.parseDouble(sc.nextLine().trim());
Flight flight = new Flight(flightID, departureCity, arrivalCity, flightDate, maxLoadWeight);
// 检查航班载重
if (totalBillingWeight > maxLoadWeight) {
System.out.printf("The flight with flight number:%s has exceeded its load capacity and cannot carry the order.", flightID);
return;
}
// 读取订单信息
Order order = new Order();
order.setOrderID(sc.nextLine().trim());
order.setOrderDate(sc.nextLine().trim());
order.setSenderaddress(sc.nextLine().trim()); // 发件人地址
order.setSendername(sc.nextLine().trim()); // 发件人姓名
order.setSenderphonenumber(sc.nextLine().trim()); // 发件人电话
order.setReceiveraddress(sc.nextLine().trim()); // 收件人地址
order.setReceivername(sc.nextLine().trim()); // 收件人姓名
order.setReceiverphonenumber(sc.nextLine().trim()); // 收件人电话
order.setFlightnumber(flight);
// 设置支付方式
String paymentType = sc.nextLine().trim();
PaymentMethod payment = paymentType.equalsIgnoreCase("Wechat") ? new WeChatPayment() :
paymentType.equalsIgnoreCase("ALiPay") ? new AlipayPayment() : new CashPayment();
order.setPayment(payment);
// 计算运费
double totalPayment = products.stream()
.mapToDouble(p -> p.calculateFreight(Math.max(p.getWeight(), p.calculateVolumeWeight())))
.sum();
totalPayment = customer.applyDiscount(totalPayment);
// 生成报告
printReport(customer, order, products, totalBillingWeight, totalPayment, payment);
}
private static void printReport(Customer customer, Order order, List<Product> products,
double totalWeight, double totalPayment, PaymentMethod payment) {
System.out.println("客户:" + customer.getName() + "(" + customer.getPhonenumber() + ")订单信息如下:");
System.out.println("-----------------------------------------");
System.out.println("航班号:" + order.getFlightnumber().getFlightID());
System.out.println("订单号:" + order.getOrderID());
System.out.println("订单日期:" + order.getOrderDate());
System.out.println("发件人姓名:" + order.getSendername());
System.out.println("发件人电话:" + order.getSenderphonenumber());
System.out.println("发件人地址:" + order.getSenderaddress());
System.out.println("收件人姓名:" + order.getReceivername());
System.out.println("收件人电话:" + order.getReceiverphonenumber());
System.out.println("收件人地址:" + order.getReceiveraddress());
System.out.println("订单总重量(kg):" + new DecimalFormat("#.0").format(totalWeight));
// 获取支付方式名称
String paymentName = payment instanceof WeChatPayment ? "微信" :
payment instanceof AlipayPayment ? "支付宝" : "现金";
System.out.println(paymentName + "支付金额:" + new DecimalFormat("#.0").format(totalPayment));
System.out.println("\n货物明细如下:");
System.out.println("-----------------------------------------");
System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费");
for (Product product : products) {
double billingWeight = Math.max(product.getWeight(), product.calculateVolumeWeight());
double freight = product.calculateFreight(billingWeight);
double rate = product.getFreightRate(billingWeight);
System.out.printf("%d\t%s\t%.1f\t%.1f\t%.1f%n",
product.getNumber(),
product.getProductName(),
billingWeight,
rate,
freight);
}
}
}
abstract class Customer {
private int customerID;
private String customerName;
private String phonenumber;
private String address;
public Customer() {}
public Customer(int customerID, String customerName, String phonenumber, String address) {
this.customerID = customerID;
this.customerName = customerName;
this.phonenumber = phonenumber;
this.address = address;
}
public int getCustomerID() { return customerID; }
public String getName() { return customerName; }
public String getPhonenumber() { return phonenumber; }
public String getAddress() { return address; }
public void setCustomerID(int customerID) { this.customerID = customerID; }
public void setName(String name) { this.customerName = name; }
public void setPhonenumber(String phonenumber) { this.phonenumber = phonenumber; }
public void setAddress(String address) { this.address = address; }
public abstract double applyDiscount(double amount);
}
class IndividualCustomer extends Customer {
public IndividualCustomer(int customerID, String name, String phone, String address) {
super(customerID, name, phone, address);
}
@Override
public double applyDiscount(double amount) {
return amount * 0.9; // 个人用户9折
}
}
class GroupCustomer extends Customer {
public GroupCustomer(int customerID, String name, String phone, String address) {
super(customerID, name, phone, address);
}
@Override
public double applyDiscount(double amount) {
return amount * 0.8; // 集团用户8折
}
}
class Product {
private int number;
private int productID;
private String productName;
private double weight;
private double length;
private double width;
private double height;
private FreightStrategy strategy;
public Product(int number, int productID, String productName, double weight, double length, double width, double height) {
this.number = number;
this.productID = productID;
this.productName = productName;
this.weight = weight;
this.length = length;
this.width = width;
this.height = height;
}
public void setCargoType(String type) {
switch (type.toLowerCase()) {
case "normal": strategy = new NormalStrategy(); break;
case "expedite": strategy = new ExpediteStrategy(); break; // 修正拼写错误
case "dangerous": strategy = new DangerousCargoStrategy(); break;
default: throw new IllegalArgumentException("无效货物类型");
}
}
public double calculateVolumeWeight() {
return (length * width * height) / 6000.0;
}
public double calculateFreight(double billingWeight) {
return strategy.calculate(billingWeight);
}
public double getFreightRate(double billingWeight) {
return strategy.getRate(billingWeight);
}
public int getNumber() { return number; }
public String getProductName() { return productName; }
public double getWeight() { return weight; }
public double getLength() { return length; }
public double getWidth() { return width; }
public double getHeight() { return height; }
}
interface FreightStrategy {
double calculate(double weight);
double getRate(double weight);
}
class NormalStrategy implements FreightStrategy {
@Override
public double calculate(double weight) {
return getRate(weight) * weight;
}
@Override
public double getRate(double weight) {
if (weight < 20) return 35;
else if (weight < 50) return 30;
else if (weight < 100) return 25;
else return 15;
}
}
class DangerousCargoStrategy implements FreightStrategy {
@Override
public double calculate(double weight) {
return getRate(weight) * weight;
}
@Override
public double getRate(double weight) {
if (weight < 20) return 80;
else if (weight < 50) return 50;
else if (weight < 100) return 30;
else return 20;
}
}
class ExpediteStrategy implements FreightStrategy { // 修正类名拼写
@Override
public double calculate(double weight) {
return getRate(weight) * weight;
}
@Override
public double getRate(double weight) {
if (weight < 20) return 60;
else if (weight < 50) return 50;
else if (weight < 100) return 40;
else return 30;
}
}
class Flight {
private String flightID;
private String departureCity;
private String arrivalCity;
private String flightDate;
private double maxLoadWeight;
public Flight() {}
public Flight(String flightID, String departureCity, String arrivalCity, String flightDate, double maxLoadWeight) {
this.flightID = flightID;
this.departureCity = departureCity;
this.arrivalCity = arrivalCity;
this.flightDate = flightDate;
this.maxLoadWeight = maxLoadWeight;
}
public String getFlightID() { return flightID; }
public String getDepartureCity() { return departureCity; }
public String getArrivalCity() { return arrivalCity; }
public String getFlightDate() { return flightDate; }
public double getMaxLoadWeight() { return maxLoadWeight; }
}
class Order {
private String orderID;
private String orderDate;
private String sendername;
private String senderphonenumber;
private String senderaddress;
private String receivername;
private String receiverphonenumber;
private String receiveraddress;
private Flight flightnumber;
private PaymentMethod payment;
public Order() {}
public String getOrderID() { return orderID; }
public void setOrderID(String orderID) { this.orderID = orderID; }
public String getOrderDate() { return orderDate; }
public void setOrderDate(String orderDate) { this.orderDate = orderDate; }
public String getSendername() { return sendername; }
public void setSendername(String sendername) { this.sendername = sendername; }
public String getSenderphonenumber() { return senderphonenumber; }
public void setSenderphonenumber(String senderphonenumber) {
this.senderphonenumber = senderphonenumber;
}
public void setFlightnumber(Flight flightnumber) {
this.flightnumber = flightnumber;
}
public Flight getFlightnumber() { return flightnumber; }
public String getSenderaddress() { return senderaddress; }
public void setSenderaddress(String senderaddress) { this.senderaddress = senderaddress; }
public String getReceivername() { return receivername; }
public void setReceivername(String receivername) { this.receivername = receivername; }
public String getReceiverphonenumber() { return receiverphonenumber; }
public void setReceiverphonenumber(String receiverphonenumber) {
this.receiverphonenumber = receiverphonenumber;
}
public String getReceiveraddress() { return receiveraddress; }
public void setReceiveraddress(String receiveraddress) {
this.receiveraddress = receiveraddress;
}
public void setPayment(PaymentMethod method) {
this.payment = method;
}
public PaymentMethod getPayment() { // 新增getter方法
return payment;
}
public void processPayment(double amount) {
payment.pay(amount);
}
}
interface PaymentMethod {
void pay(double amount);
}
class WeChatPayment implements PaymentMethod {
public void pay(double amount) {
// 微信支付实现
}
}
class AlipayPayment implements PaymentMethod {
public void pay(double amount) {
// 支付宝支付实现
}
}
class CashPayment implements PaymentMethod {
public void pay(double amount) {
// 现金支付实现
}
}
类图:

报表: ![]()
航空货运管理系统质量分析报告
一、核心问题定位
// Product.java
public void setCargoType(String type) {
if (type.equals("DANGEROUS")) {
if (weight > 50) {
// 嵌套逻辑...
} else if (...) {
// 更多嵌套...
}
}
// 共4层嵌套...
}
🚨 严重问题
- setCargoType方法:复杂度5(超标临界值4)
- 嵌套深度达4层(建议≤3)
- 包含12条语句(推荐≤10)
二、质量指标总览
| 文件 | 方法数 | 平均复杂度 | 分支覆盖率 |
|---|---|---|---|
| Main8.java | 2 | 3.0 | 1.7% |
| Product.java | 11 | 1.36 | 18.4% |
三、架构亮点
✅ 优秀实践
- FreightStrategy.java:完美实现策略模式
- 分支覆盖率30%(高于平均水平)
- 支付模块轻松扩展现金支付方式
四、改进方案
🔧 重构建议
- 将Main8拆分为:
- OrderService(订单处理)
- PaymentProcessor(支付逻辑)
- 使用状态模式重构setCargoType方法
- 为复杂度>3的方法增加单元测试
三.踩坑与心得:
当运费计算变成"俄罗斯套娃"
// 初版的天真写法
public double calculateFreight() {
if (type == "dangerous") {
if (weight > 50) {
if (...) { /* 更多嵌套 */ }
}
} // 后续还有7层...
}
客户折扣的"身份危机"
旧方案
if (customerType.equals("VIP")) {
// 折扣逻辑
} // 每次新增类型都要改这里
体会:当发现代码里总在用if-else区分不同类型时,就是该用继承和多态的信号了。
支付模块没搞出具体实现
// 初版交作业时的尴尬
class WeChatPayment {
void pay(double amount) {
// 留空待实现...
}
}
后续改进
- 增加了支付日志记录
- 实现真正的支付接口调用
- 添加了支付异常处理
四.改进建议:
在开发这个航空货运系统的过程中,我发现代码质量有几个明显的提升空间。首先是方法拆分方面,很多方法都过于臃肿,比如运费计算方法里塞了太多条件判断,导致后期维护困难。建议把这些大方法拆分成小方法,每个方法只做一件事。比如可以把费率计算单独抽出来,重量校验也独立成方法,这样主方法就清爽多了。
代码中的嵌套层次太深也是个问题,特别是运费计算那里有好几层if-else嵌套,看着就头晕。建议用卫语句提前返回,或者把嵌套逻辑抽成独立方法。比如遇到非法参数直接返回,不要继续往下走。对于复杂的条件判断,可以考虑用策略模式或者工厂模式来替代,这样代码结构会更清晰。
注释方面目前做得还不够,特别是业务逻辑复杂的地方缺少必要的说明。建议在以下地方加注释:类头部说明这个类的职责,方法前说明业务逻辑和参数要求,复杂算法处加上实现思路。但要注意避免过度注释,好的代码应该自解释,只在必要的地方加注释。
异常处理可以做得更完善些。现在很多地方直接吞掉异常或者简单打印,建议定义业务异常类,在适当的地方捕获处理。比如重量为负数时应该抛出带明确提示的异常,而不是任由系统报错。支付失败也应该有专门的异常处理逻辑。
日志记录也需要加强,特别是在业务流程的关键节点。比如订单创建、运费计算、支付完成等重要操作都应该记录日志,方便后续排查问题。建议用日志级别区分重要性,比如debug日志记录详细流程,error日志记录异常情况。
代码重复问题也值得关注,比如各种校验逻辑散落在各处。建议把公共的校验逻辑抽成工具方法,比如参数非空检查、数值范围校验等。这样既避免重复,又保持校验标准统一。
对于经常变化的业务规则,比如运费费率、折扣策略等,建议设计成可配置的。可以把这些规则放到数据库或配置文件中,避免每次修改都要改代码。这样运营人员调整规则时就不需要开发介入。
最后提一下测试,目前单元测试覆盖不足。建议为每个业务方法编写测试用例,特别是边界条件要多测试。比如刚好卡在费率分界点的重量,最大最小的尺寸等。测试用例要随着代码一起维护,确保每次修改都不会破坏原有功能。
这些改进不用一次性全做完,可以分阶段逐步优化。每次修改一个小点,确保测试通过后再继续。保持代码整洁需要持续投入,但长远来看会大大降低维护成本。
五.总结:
✈️ 航空货运系统开发总结
🔧 技术实践收获
通过这次项目,深刻体会到策略模式对复杂业务规则的解耦能力。将运费计算从最初的多层if-else重构为策略模式后,新增货物类型再也不用修改核心代码,真正实现了"对扩展开放,对修改关闭"的原则。面向对象的继承特性也让客户折扣系统变得更加灵活。
📝 代码质量心得
- 方法拆分:保持方法短小精悍(20行以内)大大提升了可读性
- 减少嵌套:用卫语句替代深层嵌套,代码扁平化后调试更方便
- 注释规范:在关键算法和业务规则处添加说明,三个月后回看依然清晰
🚀 后续优化方向
计划
- 完善支付模块异常处理
- 增加输入参数校验
- 补充单元测试用例
💡 最重要体会:好的代码不是一蹴而就的,需要持续重构优化。每次提交都应该让代码比之前更整洁一点,这种渐进式改进才是可持续的开发方式。

浙公网安备 33010602011771号