封装记录Encapsulate Record
当复杂的数据结构记录需要频繁变化时,那么将其组织成一个类,对外提供变化点的函数。如果确定记录是固定数据,那么完全可以不用理会。
封装集合 Encapsulate Collection
image.png
当对一个集合做各种增删改查的操作并且有多处都需要做这种操作时,那么需要将对这个集合和各种操作封装起来,让每个调用处都统一使用这个封装起来的类。重点是对集合增删改查操作的封装。
以对象取代基本类型 Replace Primitive with Object
image.png
在开发初期,往往决定以简单的数据项表示简单的情况,比如使用数字或字符串。但随着开发的进行,你可能会发现,这些简单数据项不再那么简单了。
现在变成了high. rush. high1. rush1. high2. rush2 ……,并且有多处地方都用到了这些。
那么当再次发生变化时,你需要多处做重复的修改,并且简单的数据项不能表达当前复杂的意思了。
这时你需要封装,取消简单的数据项,改为更具含义的方式。
以查询取代临时变量 Replace Temp with Query
image.png
动机:这个临时变量真的是临时变量,只用了一次。在多处不同的地方都用到了这个计算。
做法:将计算逻辑封装成函数。在只用了一次的地方取消临时变量,直接用函数代替。在多处不同的地方统一使用这个函数,避免重复计算。
提炼类 Extract Class
image.png
动机:在实际工作中,类会不断成长扩展。
你会在这儿加入一些功能,在那儿加入一些数据。
给某个类添加一项新的责任时,你会觉得不值得为这项责任分理出一个独立的类。
于是,随着责任不断增加,这个类会变得过分复杂。很快,你的类就会变成一团乱麻。
做法:分解类所负的责任,将不同的责任封装成单独的类。
内联类 Inline Class
image.png
动机:如果一个类不再承担足够责任,不再有单独存在的理由,那么就把这个类的内容放到它本应该在的地方,然后把这个类删掉。
隐藏委托关系 Hide Delegate
image.png
动机:一个好的模块化的设计,“封装”即使不是其最关键特征,也是最关键特征之一。
“封装”意味着每个模块都应该尽可能少了解系统的其他部分。
如此一来,一旦发生变化,需要了解这一变化的模块就会比较少——这会使变化比较容易进行。
如果某些客户端先通过服务对象的字段得到另一个对象(受托类),然后调用后者的函数,那么客户就必须知晓这一层委托关系。
万一受托类修改了接口,变化会波及通过服务对象使用它的所有客户端。我可以在服务对象上放置一个简单的委托函数,将委托关系隐藏起来了,从而去除这种依赖。
这么一来,即使将来委托关系发生变化,变化也只会影响服务对象,而不会直接波及所有客户端。
“=”左边是模块1,右边是模块2,如果模块2的department发生变化,隐藏了委托关系的方式,让模块1是无感的。
移除中间人 Remove Middle Man
image.png
动机:当委托函数不断增多,服务端就会完全变成了一个中间人,此时就应该让客户的直接调用受托类。
很难说什么程度的隐藏才是合适的。
在系统运行过程中不断进行调整。
随着代码的变化,“合适的隐藏程度”这个尺度也相应改变。6个月前恰如其分的封装,现今可能就显得笨拙。
重构的意义就在于:你永远不必说对不起——只要把出问题的地方修补好就行了。
替换算法 Substitute Algorithm
image.png
动机:使用更优的算法替换旧的算法。
网友评论