重构-改善既有代码的设计完整笔记系列之8 - 重组数据
重构-改善既有代码的设计完整笔记系列之8 - 重组数据
- 8.1 Self Encapsulate Field(自封装字段)
- 8.2 Replace Data Value with Object(以对象取代数据值)
- 8.3 Change Value to Reference(将值对象改为引用对象)
- 8.4 Change Reference to Value(将引用对象改为值对象)
- 8.5 Replace Array with Object(以对象取代数组)
- 8.6 Duplicate Observed Data(复制“被监视数据”)
- 8.7 Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
- 8.8 Change Bidirectional Association to Unidirectional(将双向关联改为单向关联)
- 8.9 Replace Magic Number with Symbolic Constant(以字面常量取代魔法数)
- 8.10 Encapsulate Field(封装字段)
- 8.11 Encapsulate Collection(封装集合)
- 8.12 Replace Record with Data Class(以数据类取代记录)
- 8.13 Replace Type Code with Class(以类取代类型码)
- 8.14 Replace Type Code with Subclasses(以子类取代类型码)
- 8.15 Replace Type Code with State/Strategy(以State/Strategy取代类型码)
- 8.16 Replace Subclass with Fields(以字段取代子类)
8.1 Self Encapsulate Field(自封装字段)
为这个字段建立getter/setter函数,并且只以这些函数访问字段。
8.2 Replace Data Value with Object(以对象取代数据值)
一个数据项,需要与其他数据和行为一起使用才有意义。将数据项改成对象。
随着设计深入,数据之间的关系逐渐显现出来,就需要将相关数据及其操作封装成对象。
很明显这个_customer使用String将来的扩展会出现很多问题
class Order... private String _customer; public Order (String customer) { _customer = customer; } public String getCustomer() { return _customer; } public void setCustomer(String arg) { _customer = arg; }
8.3 Change Value to Reference(将值对象改为引用对象)
如果希望修改某个值对象的数据,并且影响到所有引用此对象的地方。
将这个值对象变成引用对象。
class Customer { public Customer(String name) { _name = name; } public String getName() { return _name; } private final String _name; } class Order { public Order(String customerName) { _customer = new Customer(customerName); } public void setCustomer(String customerName) { _customer = new Customer(customerName); } public String getCustomerName() { return _customer.getName(); } private Customer _customer; } // client code: private static int numberOfOrdersFor(Collection orders, String customer) { int result = 0; Iterator iter = orders.iterator(); while (iter.hasNext()) { Order each = (Order) iter.next(); if (each.getCustomerName().equals(customer)) result++; } return result; } class Customer { public static Customer create (String name) { return new Customer(name); } class Order { public Order (String customer) { _customer = Customer.create(customer); } class Customer { private Customer (String name) { _name = name; }
8.4 Change Reference to Value(将引用对象改为值对象)
引用对象很小且不可变,将它改成一个值对象.需要先明确是否要将目标改为不可变对象。
以下类在new的时候是不同的对象
class Currency { private String _code; public Currency(String _code) { super(); this._code = _code; } public String getCode() { return _code; } } //测试 System.out.println(new Currency("RMB").equals(new Currency("RMB"))); //结果是false //如果改为不可变对象,即增加 public boolean equals(Object arg) { if (!(arg instanceof Currency)) return false; Currency other = (Currency) arg; return (_code.equals(other._code)); } public int hashCode() { return _code.hashCode(); } System.out.println(new Currency("RMB").equals(new Currency("RMB"))); //结果是true
8.5 Replace Array with Object(以对象取代数组)
数组中的元素各自代表不同的东西。
以对象替换数组,对于数组中的每个元素,以一个字段来表示
row [0] = "Liverpool"; row [1] = "15"; String name = row[0]; int wins = Integer.parseInt(row[1]); //就是转成类的字段。
8.6 Duplicate Observed Data(复制“被监视数据”)
略
8.7 Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
两个类都需要使用对方特性,但其间只有一条单向连接。
添加一个反向指针,并使修改函数能够同时更新2条连接。
8.8 Change Bidirectional Association to Unidirectional(将双向关联改为单向关联)
两个类之间有双向关联,但其中一个类如今不再需要另一个类的特性。去除不必要的关联。
避免双向关联可能造成的”僵尸对象“
8.9 Replace Magic Number with Symbolic Constant(以字面常量取代魔法数)
你有一个字面数值,带有特别含义。
创建一个常量,根据其意义为它命名,并将上述的字面数值替换为这个常量。
double potentialEnergy(double mass, double height) { return mass * 9.81 * height; } //换成: double potentialEnergy(double mass, double height) { return mass * GRAVITATIONAL_CONSTANT * height; } static final double GRAVITATIONAL_CONSTANT = 9.81;
8.10 Encapsulate Field(封装字段)
你的类中存在一个public字段。将它声明为private,并提供相应的访问函数。
和8.1雷同
8.11 Encapsulate Collection(封装集合)
如果一个函数返回一个集合,应改为返回该集合的一个只读副本,并在这个类中提供添加/移除集合元素的函数。
8.12 Replace Record with Data Class(以数据类取代记录)
略
8.13 Replace Type Code with Class(以类取代类型码)
略
8.14 Replace Type Code with Subclasses(以子类取代类型码)
略
8.15 Replace Type Code with State/Strategy(以State/Strategy取代类型码)
你有一个类型码,它会影响类的行为,但你无法提供继承手法消除它。以状态对象替代类型码。
8.16 Replace Subclass with Fields(以字段取代子类)
你的各个子类的唯一差别只在“返回常量数据”的函数身上。
修改这些函数,使它们返回超类中的某个字段(新增),然后销毁子类。
抽象类和子类:
abstract class Person { abstract boolean isMale(); abstract char getCode(); } ... class Male extends Person { boolean isMale() { return true; } char getCode() { return 'M'; } } class Female extends Person { boolean isMale() { return false; } char getCode() { return 'F'; } } //去除不必要的子类即可: class Person{ private final boolean _isMale; ... }
目前维护的开源产品:https://gitee.com/475660