重构的基本手法有很多,可以大致分为以下几类:
1. 重新组织函数 (Composing Methods)
- 提炼函数 (Extract Method): 将一段代码从一个较长的函数中提取出来,形成一个新的独立函数。
- 内联函数 (Inline Method): 将一个函数的代码直接复制到调用它的地方,消除函数调用的开销。
- 内联临时变量 (Inline Temp): 将一个只被赋值一次的临时变量替换成它的表达式。
- 以查询取代临时变量 (Replace Temp with Query): 将一个临时变量替换成一个返回值的函数调用。
- 引入解释性变量 (Introduce Explaining Variable): 将一个复杂的表达式赋值给一个新的变量,并用一个有意义的名称来解释它的含义。
- 分解临时变量 (Split Temporary Variable): 将一个临时变量分解成多个变量,每个变量只负责一个特定的功能。
- 移除对参数的赋值 (Remove Assignments to Parameters): 创建一个临时变量来代替被修改的参数。
- 以函数对象取代函数 (Replace Method with Method Object): 将一个函数转换成一个带有方法的对象,以便在方法中使用局部变量。
- 替换算法 (Substitute Algorithm): 将一个函数的算法替换成另一个更清晰或更高效的算法。
2. 在对象之间搬移特性 (Moving Features Between Objects)
- 搬移函数 (Move Method): 将一个函数从一个类移动到另一个更合适的类。
- 搬移字段 (Move Field): 将一个字段从一个类移动到另一个更合适的类。
- 提炼类 (Extract Class): 将一个类的部分代码和数据提取出来,形成一个新的类。
- 内联类 (Inline Class): 将一个类的所有特性都移动到另一个类中,然后删除这个类。
- 隐藏委托关系 (Hide Delegate): 封装一个对象的委托关系,使其对外部不可见。
- 移除中间人 (Remove Middle Man): 移除一个不必要的委托对象,直接访问目标对象。
- 引入外加函数 (Introduce Foreign Method): 在一个类中添加一个函数,用于调用另一个类的方法。
- 引入本地扩展 (Introduce Local Extension): 创建一个新的类来扩展一个已有的类,而不修改原有的类。
3. 重新组织数据 (Organizing Data)
- 自封装字段 (Self Encapsulate Field): 通过访问器方法来访问和修改一个字段,而不是直接访问它。
- 以对象取代数据值 (Replace Data Value with Object): 将一个数据值转换成一个对象。
- 将值对象改为引用对象 (Change Value to Reference): 将一个值对象转换成一个引用对象。
- 将引用对象改为值对象 (Change Reference to Value): 将一个引用对象转换成一个值对象。
- 以对象取代数组 (Replace Array with Object): 将一个数组转换成一个对象,使用字段来代替数组元素。
- 复制“被监视数据” (Duplicate Observed Data): 将一个被多个对象监视的数据复制到每个对象中,以便解耦。
- 将单向关联改为双向关联 (Change Unidirectional Association to Bidirectional): 将一个单向关联转换成一个双向关联。
- 将双向关联改为单向关联 (Change Bidirectional Association to Unidirectional): 将一个双向关联转换成一个单向关联。
- 以字面常量取代魔法数 (Replace Magic Number with Symbolic Constant): 将一个没有明确含义的数字常量替换成一个有意义的常量。
- 封装字段 (Encapsulate Field): 将一个公共字段变成私有字段,并提供访问器方法来访问和修改它。
- 封装集合 (Encapsulate Collection): 将一个集合字段变成私有字段,并提供访问器方法来访问和修改它。
4. 简化条件表达式 (Simplifying Conditional Expressions)
- 分解条件表达式 (Decompose Conditional): 将一个复杂的条件表达式分解成多个简单的条件表达式。
- 合并条件表达式 (Consolidate Conditional Expression): 将多个条件表达式合并成一个条件表达式。
- 合并重复的条件片段 (Consolidate Duplicate Conditional Fragments): 将重复的条件代码片段提取出来,形成一个独立的函数。
- 移除控制标记 (Remove Control Flag): 将一个控制标记替换成一个更清晰的控制结构,例如 break 或 return 语句。
- 以卫语句取代嵌套条件表达式 (Replace Nested Conditional with Guard Clauses): 将一个嵌套的条件表达式替换成多个卫语句,每个卫语句处理一个特定的条件。
- 以多态取代条件表达式 (Replace Conditional with Polymorphism): 将一个条件表达式替换成多态调用,根据对象的类型来执行不同的行为。
- 引入 Null 对象 (Introduce Null Object): 创建一个 Null 对象来代替 null 值,避免 NullPointerException。
5. 简化函数调用 (Simplifying Method Calls)
- 添加参数 (Add Parameter): 向一个函数添加一个参数。
- 移除参数 (Remove Parameter): 从一个函数中移除一个参数。
- 将查询函数和修改函数分离 (Separate Query from Modifier): 将一个既查询数据又修改数据的函数分解成两个函数,一个只查询数据,另一个只修改数据。
- 参数化方法 (Parameterize Method): 将一个函数中的硬编码值替换成参数。
- 以明确函数取代参数 (Replace Parameter with Explicit Methods): 将一个根据参数值执行不同行为的函数分解成多个函数,每个函数对应一个特定的参数值。
- 保持对象完整 (Preserve Whole Object): 将一个对象的多个字段作为参数传递给一个函数,替换成将整个对象传递给函数。
- 以函数取代参数 (Replace Parameter with Methods): 将一个根据参数值执行不同行为的函数分解成多个函数,每个函数对应一个特定的参数值,并由调用者根据条件选择调用哪个函数。
6. 处理概括关系 (Dealing with Generalization)
- 字段上移 (Pull Up Field): 将一个子类中的字段移动到父类中。
- 函数上移 (Pull Up Method): 将一个子类中的函数移动到父类中。
- 构造函数本体上移 (Pull Up Constructor Body): 将一个子类构造函数中的代码移动到父类构造函数中。
- 字段下移 (Push Down Field): 将一个父类中的字段移动到子类中。
- 函数下移 (Push Down Method): 将一个父类中的函数移动到子类中。
- 提炼子类 (Extract Subclass): 将一个类的一部分特性提取出来,形成一个新的子类。
- 提炼超类 (Extract Superclass): 将多个类的共同特性提取出来,形成一个新的超类。
- 折叠继承体系 (Collapse Hierarchy): 将一个继承体系中的冗余类合并。
- 塑造模板函数 (Form Template Method): 将一个算法的框架定义在父类中,并将具体的步骤延迟到子类中实现。
- 以委托取代继承 (Replace Inheritance with Delegation): 将继承关系替换成委托关系。
- 以继承取代委托 (Replace Delegation with Inheritance): 将委托关系替换成继承关系。