LotusLoveNature

日常工作,生活小记

看重构记录二

这次的重点是对象间的优化重构。

1. Self Encapsulate Field 自我封装值域

   将一些私有属性的访问,用get、set方法来替换,有几个好处,一个是阅读代码的时候知道它就是一个取值函数,不用停下来。另一方面,完成属性自我封装后,如果有子类继承,subclass可以根据需要覆写取值函数

2. Replace Data Value with Object 用对象来替换Value值

  开发初期将一些简单的内容用单个属性表示,后来为了扩展,可能需要扩充,这时就要用到将值替换成对象。替换方法就是创建一个类,并将原属性移过来,加上取值函数,在声明原属性的地方用类引用替换,用原属性的地方用类引用的取值函数

3. Change Value to Reference 值对象改变为引用对象

 如果你有一个class,可以衍生出许多实体,但是你想合并为一个,这不就是单例。实值对象比如日期,钱,引用对象比如账号,客户。值一般可以存在很多份而你也不介意,比如工资可以由币种,数量表示,每个工资的对象都是不可变的,也就是如果你要表示一个新的工资,你必须重新new一个,而不是在现有的基础上进行修改。但是如果你用value object时想改变其中值,并且想影响到所有引用该对象的地方,工厂方法跟这个思想如出一辙,我们可以保存 多个对象,比如Custom1, Custom2,,,每个Custom的名字不同,这些对象我们事先就创建好,而不是动态创建的,那么我们的构造方法时私有的。在需要的只要去获取就可以了。可以保证同类Custom所获得的对象是同一个。这个对象就是Reference

4. Change Reference to Value 将引用对象变为实值

与3刚好相反,这个过程就是去工程的过程,当然要考虑这个值对象是否可以保证是不可变的。简历equals方法和hashCode方法,删除共有的工厂方法

5. Replace Array With Object 用对象来替换数组

  比如圆,半径,圆点,我们可以用a[0] = r, a[1] = point表示。但是换成对象,就是Object【r, point】,用数组有个弊端就是你必须规范数组的定义,比如这里“数组的第一个数据是半径”,但是对象不同,你可以用属性名称和方法来记录他们。我就刚重构过一个数组转化为对象的例子,那是一批二维数组,但是转化为对象后,就变成对象数组,省去了一长串数组的定义和规范定义

6. Duplicate Observed Data

   如果数据是被观察的,数据和UI的逻辑在一起,这样比较复杂,我们可以尝试将Data与UI分离,将所有数据的处理放在Data中,UI只处理界面相关,Data与UI之间通信可以采用观察者模型,或者监听器。如果是观察者模型,UI实现Observer,是观察者,Data是被观察extends Observable。如果是监听器,那么UI去实现监听,Data持有监听实例,当数据逻辑变化时通知UI发生改变。

7. change unidirectional association to bidirectional 单向关联变为双向

8. 与上面相反,将双向关联变为单向

  双向连接有时候好用,但是维护起来较为麻烦,维护双向连接,确保对象正确创建和删除都增加了复杂度。而且双向关联很容易引起泄露。如果双向没必要了,就应该尽早去掉它。

9. Replace Magic Number with Symbolic Constant 以符号常量,字面常量取代魔法书

像程序中用的某个倍数因子,不要再代码里面直接写它的值,而应该用全局的常量替代之

10 .Encupsulate Field封装值域

    就是将共有属性,用私有替换,并且提供set、get方法

11.Encupsulate Collection 封装集群

    如果一个class Person有一个集群,比如List<House>那么像setList(List<House>)这样的方法去掉,添加对House的add,remove方法,addHouse(House house),removeHouse(House house)

12. Replace Record with Class 将记录性结构用类来替换

     Replace Array With Object是其一个例子

13. Replace TypeCode With Class 将型别码用类替换

    如果类型是特定的,比如people有血型,血型就只有4种,我们可以用一个类来表示血型,而不是一个int值,比如BloodGroup在这个类中我们可以创建出所有合法的型别码,比如这里的几种血型。然后people中持有的bloodType将会变成BloodGroup的一个引用。

14. Replace Typecode with subclass

 比如CellLayout里面有个类别,appType,hubType。表示两种celllayout。这时我们可以改为,新加两个类AppCelllayout,HubCelllayout,两个都继承与Celllayout。在Celllayout中声明抽象函数getType。由子类自己覆写。因为初始化Celllayout时,celllayout会接受一个参数 static Celllayout create(int type).里面根据type来初始化不同的类别的Celllayout

15. Replace Type Code with State/Strategy

当上面那种用子类替换类型码的情况不满足时,比如,type是变化的,或者类已经不再允许继承关系时 ,我们就考虑用引用替换型别码。拿上面的例子说,定义一个类CellLayoutType,里面有个抽象方法getType,CellLayout持有它的一个引用。然后定义class AppType, HubType都继承与CellLayoutType,覆写getType方法。将所有CellLayoutType中与type有关的代码变成CelllayoutType的引用实现

16. Replace subclass with TypeCode

这个是与14刚好相反的重构方法,如果子类做的事情只有区分一个类型而没有别的差异,那么子类存在的意义就不大。我们将子类覆写的superclass的抽象类在super class中自己处理,并且定义typecode,对于子类的创建方式可以用superclass的特定构造方法,将type当参数传入。如果是外界调用,我们可以通过工厂方法创建不同类型的Celllayout出来。

评论
©LotusLoveNature | Powered by LOFTER