简介
“内联类”(Inline Class)是一种重构手法,用于将一个类的功能合并到另一个类中,从而减少类的数量。这种重构手法通常用于当一个类不再承担足够的职责,或者其功能更适合放在另一个类中时。通过内联类,可以减少代码的复杂性,并提高代码的可读性和可维护性。
针对的症状(代码坏味道)
- 类职责过少(Lazy Class):当一个类的职责过少,且其功能可以合理地合并到另一个类中时。
- 过度分解(Over-Decomposition):当类的分解过于细致,导致代码难以理解和维护时。
- 类之间的耦合度过高(High Coupling):当两个类之间的耦合度过高,且其中一个类的功能可以合理地合并到另一个类中时。
内联类(Inline Class)的详细步骤
- 识别需要内联的类
- 寻找职责过少的类:在代码中找到那些职责过少,且其功能可以合理地合并到另一个类中的类。
- 评估类的独立性:确保内联的类没有独立的职责,且其功能可以合理地合并到另一个类中。
- 将类的功能合并到目标类中
- 移动字段:将需要内联的类的字段移动到目标类中。
- 移动方法:将需要内联的类的方法移动到目标类中。
- 更新引用:更新所有引用需要内联的类的地方,改为引用目标类。
- 删除原类
- 删除原类:在确保所有功能都已合并到目标类中后,删除原类。
- 测试
- 编译代码:确保代码编译通过,没有任何语法错误。
- 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
- 手动测试:如果有必要,进行手动测试以验证功能的正确性。
- 代码审查
- 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性没有下降。
- 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明内联类的影响。
示例
假设有一个类 Address,其功能可以合理地合并到 Person 类中,我们希望对其进行“内联类”的重构:
public class Person {
private String name;
private Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public Address getAddress() {
return address;
}
}
public class Address {
private String street;
private String city;
private String zipCode;
public Address(String street, String city, String zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
public String getStreet() {
return street;
}
public String getCity() {
return city;
}
public String getZipCode() {
return zipCode;
}
}
步骤如下:
- 识别需要内联的类:
Address类的职责过少,且其功能可以合理地合并到Person类中。
- 将类的功能合并到目标类中:
-
移动字段:将
Address类的字段移动到Person类中。 -
移动方法:将
Address类的方法移动到Person类中。 -
更新引用:更新所有引用
Address类的地方,改为引用Person类。public class Person { private String name; private String street; private String city; private String zipCode; public Person(String name, String street, String city, String zipCode) { this.name = name; this.street = street; this.city = city; this.zipCode = zipCode; } public String getName() { return name; } public String getStreet() { return street; } public String getCity() { return city; } public String getZipCode() { return zipCode; } }
-
- 删除原类:
- 删除
Address类。
- 删除
- 测试:
- 编译代码:确保代码编译通过,没有任何语法错误。
- 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
- 代码审查:
- 让同事审查代码,确保没有引入新的问题。
练习
基础练习题
- 内联类的字段和方法移动
-
给定以下 Java 代码,
Phone类的功能可以合理地合并到Contact类中。请将Phone类的字段和方法移动到Contact类中,并删除Phone类。public class Contact { private String name; private Phone phone; public Contact(String name, Phone phone) { this.name = name; this.phone = phone; } public String getName() { return name; } public Phone getPhone() { return phone; } } public class Phone { private String number; private String type; public Phone(String number, String type) { this.number = number; this.type = type; } public String getNumber() { return number; } public String getType() { return type; } }
-
进阶练习题
- 内联类与引用更新
-
在这段 Java 代码中,
Email类的功能可以合理地合并到User类中。请将Email类的字段和方法移动到User类中,并更新所有引用Email类的地方,改为引用User类。public class User { private String username; private Email email; public User(String username, Email email) { this.username = username; this.email = email; } public String getUsername() { return username; } public Email getEmail() { return email; } } public class Email { private String address; private boolean isVerified; public Email(String address, boolean isVerified) { this.address = address; this.isVerified = isVerified; } public String getAddress() { return address; } public boolean isVerified() { return isVerified; } }
-
综合拓展练习题
-
多模块内联与代码审查模拟
- 考虑一个简单的 Java 电商系统,有
Product类、Cart类和Order类。Cart类中的Discount类的功能可以合理地合并到Cart类中,同时Order类中的Shipping类的功能可以合理地合并到Order类中。 - 请对这些类进行 “内联类” 重构,将
Discount类和Shipping类的功能合并到Cart类和Order类中。 - 假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。
class Product { private double price; public Product(double price) { this.price = price; } public double getPrice() { return price; } } class Cart { private Product[] products; private Discount discount; public Cart(Product[] products, Discount discount) { this.products = products; this.discount = discount; } public double calculateCartTotal() { double total = 0; for (Product product : products) { total += product.getPrice(); } return discount.applyDiscount(total); } } class Discount { private double rate; public Discount(double rate) { this.rate = rate; } public double applyDiscount(double total) { return total * (1 - rate); } } class Order { private Product[] products; private Shipping shipping; public Order(Product[] products, Shipping shipping) { this.products = products; this.shipping = shipping; } public double calculateOrderTotal() { double total = 0; for (Product product : products) { total += product.getPrice(); } return total + shipping.getShippingCost(); } } class Shipping { private double cost; public Shipping(double cost) { this.cost = cost; } public double getShippingCost() { return cost; } } - 考虑一个简单的 Java 电商系统,有