重构-改善既有代码的设计完整笔记系列之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  昕友软件开发  阅读(275)  评论(0编辑  收藏  举报
欢迎访问我的开源项目:xyIM企业即时通讯