重构-改善既有代码的设计完整笔记系列之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;
...
}

 

posted @ 2020-03-19 21:49  昕友软件开发  阅读(326)  评论(0)    收藏  举报
欢迎访问我的开源项目:xyIM企业即时通讯