本文源自 infoQ 上的一篇文章,发现该篇文章非常实用,便记录于此。
该文列出了Sean Chambers 在博客中编写的一系列描述重构方式的文章。Sean指出,这些重构方式主要来源于Martin的重构资源站点、代码大全(第二版) 以及平时由他自己收集的互联网资源,他的目的是为各种重构方式提供了一些额外的描述及相关的讨论。
以下是这31篇文章列表:
- 封装集合
- 移动方法
- 提升(pull up)方法层级
- 降低(push down)方法
- 提升字段
- 降低字段
- 改名(方法,类,参数)
- 使用委派替换继承
- 提取接口
- 提取方法
- 使用策略类
- 分解依赖
- 提取方法对象
- 分离职责
- 移除重复内容
- 封装条件
- 提取父类
- 使用条件判断代替异常
- 提取工厂类
- 提取子类
- 合并继承
- 分解方法
- 引入参数对象
- 分解嵌套条件判断
- 引入契约式设计
- 避免双重否定
- 去除上帝类
- 为布尔方法命名
- 去除中间人对象
- 尽快返回
- 使用多态代替条件判断
第1天. 封装集合
某些场景下,我们并不希望直接将集合暴露给客户类,这时我们可以将集合进行封装,例如只提供对集合的增加/删除:
- public class Order {
- private List _orderLines;
- public Iterator orderLines() {
- return _orderLines.iterator();
- }
- public void addOrderLine(OrderLine orderLine) {
- _orderLines.add(orderLine);
- }
- public void removeOrderLine(OrderLine orderLine) {
- _orderLines.remove(orderLine);
- }
- }
public class Order {
private List _orderLines;
public Iterator orderLines() {
return _orderLines.iterator();
}
public void addOrderLine(OrderLine orderLine) {
_orderLines.add(orderLine);
}
public void removeOrderLine(OrderLine orderLine) {
_orderLines.remove(orderLine);
}
}
第2天. 移动方法
如果一个方法在某个类中所使用的次数要远远多于它本身所在的类,那么很可能该方法应隶属于前一个类。
第3天. 提升方法层级
当多个子类都需要某个方法时,那么需要将这个方法从各子类级别提升到该继承体系中的上一级。
第4天. 降低方法层级
与第3天重构相反,当只有个别子类需要某方法时,不妨将该方法从父类中移至该子类。
第5天. 提升字段
与提升方法层级类似,这里需要提升的是字段。
第6天. 降低字段
与降低方法层级类似,这里需要降低的是字段。
第7天. 改名(方法,类,参数)
当方法名,类名,或参数名称不具有描述性,没有含义,或表达不恰当时,需要对这些名称进行重构。
第8天. 使用委派代替继承
这是老生常谈了,has-a is better than is-a。继承打破了类之间的封装性,某些情况下,基类的改变将导致子类行为异常(<Effective Java)。据说,James Gosling对于他所设计的Java语言最后悔的一件事就是允许继承。所以,只有真正是 is-a 的关系时,方可使用继承。
第9天. 提取接口
当不止一个类使用同一个类的方法集合时,那么最好为后者提取出一个接口,以实现解耦。
第10天. 提取方法
简单地来讲,就是一个方法只做一件事,不要在一个方法中糅合多个逻辑。
第11天. 使用策略模式代替switch
如果 switch-case 中的 case 条件经常发生变动(如增加或移除),那么不妨使用策略模式代替之。详见 Switch to Strategy
第12天. 分解依赖
引入中间类分解依赖。
第13天. 提取方法对象
与提取方法类似,只不过要把这些方法放在适合它们的类中。
第14天. 分离职责
单一责任原则,即一个类只做它该做的事情。如果该类所提供的各接口之间不相关,那么把这些不相关的接口分离出去。
第15天. 移除重复内容
一段类似代码多次重复出现,那么最好将它们整合到一个方法中,实现代码共享。
第16天. 封装条件
如果一个条件检查涉及到多个判断,那么最好将这个条件检查提取出来成为一个属性或一个方法,这样有利于程序阅读。
第17天. 提取父类
与第3天的<提升方法层级>类似,区别是在本重构中父类尚不存在,这时需新建父类,然后将方法提升级别至这个父类,以便于父类的其它子类也能共享这些方法。
第18天. 使用条件判断代替异常
本重构是指不要滥用异常处理来控制程序流。
第19天. 提取工厂类
抽象工厂或工厂方法。
第20天. 提取子类
与第4天<降低方法层级>类似,区别是将方法降低到的低级别子类尚不存在,需新建。
第21天. 合并继承
今日重构方法是指,当子类功能其实是可以合并到父类中,那么何必还要多出一个子类呢?
第22天. 分解方法
将一个大方法分成若干小方法进行调用,而不是将逻辑都放在一个大方法里,难以阅读。
第23天. 引入参数对象
当参数个数太多时,是非常不利于客户使用该 API 的,因为这样的方法难以阅读和理解。重构办法是,引入参数对象,将参数组织成适当的对象作为方法参数。
第24天. 分解嵌套条件判断
典型的嵌套条件判断是多层的 if-else 判断,这使得程序不那么易读。典型场景是在方法开始时检查参数,只有所有参数都符合需求时,才开始执行方法功能。不妨逐个检查参数,不符合要求时,马上退出方法。
第25天. 引入契约式设计
Design By Contract or DBC。本条重构个人觉得纯属扯蛋,不能称之为重构。
第26天. 避免双重否定
双重否定难以理解,比如
if ( !customer.IsNotFlagged ) {
...
}
改为
if (customer.IsFlagged) {
...
}
更易于理解
第27天. 去除上帝类
上帝类是指那些融合了各种功能的类,往往造成该类职责不清,该有的有,不该有的也有。典型的如以manager,util 结尾的类。重构方法是,将这些方法分解到适合它们的类中。
第28天. 为布尔方法重命名
还是见原文吧。
第29天. 去除中间人对象
中间人对象是指某对象只是简单的将方法调用转发给目标对象,而其本身并没有做任何工作,留之纯属多余,干脆去掉。
第30天. 尽快返回
与第24天<分解嵌套条件判断>类似,条件不符合则马上返回结果。
第31天. 使用多态代替条件判断
如果需要根据对象所属类型进而做某些工作,那么最好改用多态。