码 (即空白位置也是相同的),但是变量使用不同的值。这种复制并不会出现在 CPD 之类的工具中,因为重复的基础设施的每个实例的值必须是惟一的。尽管如 此,它仍然会损害您的代码。
下面举一个例子。我使用一个包含若干字段的简单 employee 类,如清单 4 所示:
清单 4. 一个简单 employee 类
public class Employee {
private String name;
private int salary;
private int hireYear;
public Employee(String name, int salary, int hireYear) {
this.name = name;
this.salary = salary;
this.hireYear = hireYear;
}
public String getName() { return name; }
public int getSalary() { return salary;}
public int getHireYear() { return hireYear; }
}
演化架构与紧急设计:对设计进行重构(5)
时间:2011-05-18 IBM Neal Ford
对于这个简单类,我希望能够对类的任意字段进行排序。Java 语言中的一种 机制可以通过创建实现 Comparator 接口的 comparator 类,改变排序次序。清 单 5 展示了 name 和 salary 的 Comparator:
清单 5. name 和 salary 的 Comparator
public class EmployeeNameComparator implements Comparator<Employee> {
public int compare(Employee emp1, Employee emp2) {
return emp1.getName().compareTo(emp2.getName());
}
}
public class EmployeeSalaryComparator implements Comparator<Employee> {
public int compare(Employee emp1, Employee emp2) {
return emp1.getSalary() - emp2.getSalary();
}
}
对于 Java 开发人员来说,这看上去非常自然。然而,考虑图 4 所示的代码 视图,我在其中将两个 Comparator 重叠:
图 4. 重叠后的 comparator
可以看到,相同的空白,不同的值 可以很好地形容这个情况。大部分代码是 经过复制的;惟一不同的部分是返回的值。由于我以一种 “自然” 的方式使用 了比较基础设施(即按语言设计者的意图使用),因此很难发现这种复制,但是 它确实存在于代码中。也许对于区区三个属性来说不算太严重,但是如果增长到 大量属性呢?您决定什么时候开始处理这种复制,您打算怎么对付它?
我准备使用反射(reflection)来创建一种通用的排序基础设施,其中不会涉 及大量复制的样板代码。为此,我创建了一个类来为每个字段自动处理 comparator 的排序和创建。清单 6 展示了 EmployeeSorter 类:
清单 6. EmployeeSorter 类
public class EmployeeSorter {
public void sort(List<DryEmployee> employees, String criteria) {
Collections.sort(employees, getComparatorFor (criteria));
}
private Method getSelectionCriteriaMethod(String methodName) {
Method m;
methodName = "get" + methodName.substring(0, 1).toUpperCase() +
methodName.substring(1);
try {
m = DryEmployee.class.getMethod(methodName);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage());
}
return m;
}
public Comparator<DryEmployee> getComparatorFor(final String field) {
return new Comparator<DryEmployee>() {
public int compare(DryEmployee o1, DryEmplo
|