简介
"引入特殊情况类"(Introduce Special Case)是一种重构手法,通过创建一个特殊的类来处理某些特殊情况,从而减少代码中的重复条件检查。这种方法特别适用于那些需要频繁检查某个对象是否为 null
或其他特殊值的情况。以下是进行"引入特殊情况类"重构的详细步骤:
针对的症状(代码坏味道)
- 重复的条件检查(Repeated Conditional Checks)
- 过多的
null
检查(Excessive Null Checks)
引入特殊情况类(Introduce Special Case)的详细步骤
- 识别需要处理的特殊情况
- 寻找代码中频繁出现的条件检查,特别是
null
检查。 - 确定这些条件检查是否可以被封装到一个特殊的类中。
- 寻找代码中频繁出现的条件检查,特别是
- 创建特殊情况类
- 创建一个新的类来表示特殊情况。
- 为这个类实现与正常情况相同的接口或方法,但返回特殊值或执行特殊操作。
- 替换条件检查
- 将代码中的条件检查替换为对特殊情况类的使用。
- 确保所有相关的地方都使用新的特殊情况类。
- 测试
- 编译代码:确保代码编译通过,没有任何语法错误。
- 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
- 手动测试:如果有必要,进行手动测试以验证功能的正确性。
- 代码审查
- 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性没有下降。
- 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明引入特殊情况类的影响。
示例
假设有一个方法 getCustomerName,其中包含对 null
的频繁检查,我们希望对其进行"引入特殊情况类"的重构:
java
public class Customer {
private String name;
public Customer(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Order {
private Customer customer;
public Order(Customer customer) {
this.customer = customer;
}
public String getCustomerName() {
return (customer == null) ? "Unknown Customer" : customer.getName();
}
}
步骤如下:
-
识别需要处理的特殊情况:
- 频繁的
null
检查:customer == null
。
- 频繁的
-
创建特殊情况类:
-
创建一个新的类
UnknownCustomer
来表示特殊情况:javapublic class UnknownCustomer extends Customer { public UnknownCustomer() { super("Unknown Customer"); } }
-
-
替换条件检查:
-
将
null
检查替换为对UnknownCustomer
的使用:javapublic class Order { private Customer customer; public Order(Customer customer) { this.customer = (customer == null) ? new UnknownCustomer() : customer; } public String getCustomerName() { return customer.getName(); } }
-
-
测试:
- 编译代码:确保代码编译通过,没有任何语法错误。
- 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
-
代码审查:
- 让同事审查代码,确保没有引入新的问题。
练习
基础练习题
-
引入简单特殊情况类
-
给定以下 Java 代码,getProductPrice方法中有频繁的
null
检查。请引入特殊情况类来封装这些检查。javapublic class Product { private double price; public Product(double price) { this.price = price; } public double getPrice() { return price; } } public class Order { private Product product; public Order(Product product) { this.product = product; } public double getProductPrice() { return (product == null) ? 0.0 : product.getPrice(); } }
-
-
引入复杂特殊情况类
-
下面的 Java 代码中有两个方法getCustomerName和getCustomerAddress,都包含频繁的
null
检查。请引入特殊情况类来封装这些检查。javapublic class Customer { private String name; private String address; public Customer(String name, String address) { this.name = name; this.address = address; } public String getName() { return name; } public String getAddress() { return address; } } public class Order { private Customer customer; public Order(Customer customer) { this.customer = customer; } public String getCustomerName() { return (customer == null) ? "Unknown Customer" : customer.getName(); } public String getCustomerAddress() { return (customer == null) ? "Unknown Address" : customer.getAddress(); } }
-
进阶练习题
-
引入复杂逻辑特殊情况类
-
在这段 Java 代码中,calculateShippingCost方法内有频繁的
null
检查。请引入特殊情况类来封装这些检查。javapublic class ShippingInfo { private double baseShippingCost; private double discountRate; public ShippingInfo(double baseShippingCost, double discountRate) { this.baseShippingCost = baseShippingCost; this.discountRate = discountRate; } public double getBaseShippingCost() { return baseShippingCost; } public double getDiscountRate() { return discountRate; } } public class Order { private ShippingInfo shippingInfo; public Order(ShippingInfo shippingInfo) { this.shippingInfo = shippingInfo; } public double calculateShippingCost() { return (shippingInfo == null) ? 0.0 : shippingInfo.getBaseShippingCost() - (shippingInfo.getBaseShippingCost() * shippingInfo.getDiscountRate()); } }
-
-
引入方法与返回值特殊情况类
-
给定以下 Java 代码,processData方法包含频繁的
null
检查。请引入特殊情况类来封装这些检查。javaimport java.util.ArrayList; import java.util.List; public class DataProcessor { public int processData(int[] dataArray) { if (dataArray == null) { return 0; } List<Integer> processedData = new ArrayList<>(); for (int num : dataArray) { num = num * 2; if (num > 10) { num = num - 5; } processedData.add(num); } int sum = 0; for (int num : processedData) { sum += num; } return sum; } }
-
综合拓展练习题
- 多模块引入特殊情况类与代码审查模拟
-
考虑一个简单的 Java 电商系统,有Product类、Cart类和Order类。Cart类中的calculateCartTotal方法和Order类中的calculateOrderTotal方法都有频繁的
null
检查,同时Cart类中的applyCartDiscount方法也有频繁的null
检查。 -
请对这些方法进行 "引入特殊情况类" 重构,将频繁的
null
检查封装到特殊情况类中。 -
假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。
javaclass Product { private double price; public Product(double price) { this.price = price; } public double getPrice() { return price; } } class Cart { private Product[] products; private double discountRate; public Cart(Product[] products, double discountRate) { this.products = products; this.discountRate = discountRate; } public double calculateCartTotal() { if (products == null) { return 0.0; } double total = 0; for (Product product : products) { if (product == null) { continue; } total += product.getPrice(); } return total - (total * discountRate); } public void applyCartDiscount() { if (products == null) { return; } if (products.length > 3) { discountRate += 0.05; } if (calculateCartTotal() > 100) { discountRate += 0.1; } } } class Order { private Product[] products; private double shippingCost; public Order(Product[] products, double shippingCost) { this.products = products; this.shippingCost = shippingCost; } public double calculateOrderTotal() { if (products == null) { return 0.0; } double total = 0; for (Product product : products) { if (product == null) { continue; } total += product.getPrice(); } return total + shippingCost; } }
-