auto commit
This commit is contained in:
parent
96e3b0ac73
commit
7a686e21ab
354
notes/重构.md
354
notes/重构.md
|
@ -44,69 +44,69 @@
|
|||
* [8. 以函数对象取代函数](#8-以函数对象取代函数)
|
||||
* [9. 替换算法](#9-替换算法)
|
||||
* [六、在对象之间搬移特性](#六在对象之间搬移特性)
|
||||
* [1. Move Method(搬移函数)](#1-move-method搬移函数)
|
||||
* [2. Move Field(搬移字段)](#2-move-field搬移字段)
|
||||
* [3. Extract Class(提炼类)](#3-extract-class提炼类)
|
||||
* [4. Inline Class(将类内联化)](#4-inline-class将类内联化)
|
||||
* [5. Hide Delegate(隐藏“委托关系”)](#5-hide-delegate隐藏“委托关系”)
|
||||
* [6. Remove Middle Man(移除中间人)](#6-remove-middle-man移除中间人)
|
||||
* [7. Introduce Foreign Method(引入外加函数)](#7-introduce-foreign-method引入外加函数)
|
||||
* [8. Introduce Local Extension(引入本地扩展)](#8-introduce-local-extension引入本地扩展)
|
||||
* [1. 搬移函数](#1-搬移函数)
|
||||
* [2. 搬移字段](#2-搬移字段)
|
||||
* [3. 提炼类](#3-提炼类)
|
||||
* [4. 将类内联化](#4-将类内联化)
|
||||
* [5. 隐藏委托关系](#5-隐藏委托关系)
|
||||
* [6. 移除中间人](#6-移除中间人)
|
||||
* [7. 引入外加函数](#7-引入外加函数)
|
||||
* [8. 引入本地扩展](#8-引入本地扩展)
|
||||
* [七、重新组织数据](#七重新组织数据)
|
||||
* [1. Self Encapsulate Field(自封装字段)](#1-self-encapsulate-field自封装字段)
|
||||
* [2. Replace Data Value with Object(以对象取代数据值)](#2-replace-data-value-with-object以对象取代数据值)
|
||||
* [3. Change Value to Reference(将值对象改成引用对象)](#3-change-value-to-reference将值对象改成引用对象)
|
||||
* [4. Change Reference to value(将引用对象改为值对象)](#4-change-reference-to-value将引用对象改为值对象)
|
||||
* [5. Replace Array with Object(以对象取代数组)](#5-replace-array-with-object以对象取代数组)
|
||||
* [6. Duplicate Observed Data(赋值“被监视数据”)](#6-duplicate-observed-data赋值“被监视数据”)
|
||||
* [7. Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)](#7-change-unidirectional-association-to-bidirectional将单向关联改为双向关联)
|
||||
* [8. Change Bidirectional Association to Unidirectional(将双向关联改为单向关联)](#8-change-bidirectional-association-to-unidirectional将双向关联改为单向关联)
|
||||
* [9. Replace Magic Number with Symbolic Constant(以字面常量取代魔法数)](#9-replace-magic-number-with-symbolic-constant以字面常量取代魔法数)
|
||||
* [10. Encapsulate Field(封装字段)](#10-encapsulate-field封装字段)
|
||||
* [11. Encapsulate Collection(封装集合)](#11-encapsulate-collection封装集合)
|
||||
* [12. Replace Record with Data Class(以数据类取代记录)](#12-replace-record-with-data-class以数据类取代记录)
|
||||
* [13. Replace Type Code with Class(以类取代类型码)](#13-replace-type-code-with-class以类取代类型码)
|
||||
* [14. Replace Type Code with Subcalsses(以子类取代类型码)](#14-replace-type-code-with-subcalsses以子类取代类型码)
|
||||
* [15. Replace Type Code with State/Strategy (以 State/Strategy 取代类型码)](#15-replace-type-code-with-statestrategy-以-statestrategy-取代类型码)
|
||||
* [16. Replace Subclass with Fields(以字段取代子类)](#16-replace-subclass-with-fields以字段取代子类)
|
||||
* [1. 自封装字段](#1-自封装字段)
|
||||
* [2. 以对象取代数据值](#2-以对象取代数据值)
|
||||
* [3. 将值对象改成引用对象](#3-将值对象改成引用对象)
|
||||
* [4. 将引用对象改为值对象](#4-将引用对象改为值对象)
|
||||
* [5. 以对象取代数组](#5-以对象取代数组)
|
||||
* [6. 赋值被监视数据](#6-赋值被监视数据)
|
||||
* [7. 将单向关联改为双向关联](#7-将单向关联改为双向关联)
|
||||
* [8. 将双向关联改为单向关联](#8-将双向关联改为单向关联)
|
||||
* [9. 以字面常量取代魔法数](#9-以字面常量取代魔法数)
|
||||
* [10. 封装字段](#10-封装字段)
|
||||
* [11. 封装集合](#11-封装集合)
|
||||
* [12. 以数据类取代记录](#12-以数据类取代记录)
|
||||
* [13. 以类取代类型码](#13-以类取代类型码)
|
||||
* [14. 以子类取代类型码](#14-以子类取代类型码)
|
||||
* [15. 以 State/Strategy 取代类型码](#15-以-statestrategy-取代类型码)
|
||||
* [16. 以字段取代子类](#16-以字段取代子类)
|
||||
* [八、简化条件表达式](#八简化条件表达式)
|
||||
* [1. Decompose Conditional(分解条件表达式)](#1-decompose-conditional分解条件表达式)
|
||||
* [2. Consolidate Conditional Expression(合并条件表达式)](#2-consolidate-conditional-expression合并条件表达式)
|
||||
* [3. Consolidate Duplicate Conditional Fragments (合并重复的条件片段)](#3-consolidate-duplicate-conditional-fragments-合并重复的条件片段)
|
||||
* [4. Remove Control Flag(移除控制标记)](#4-remove-control-flag移除控制标记)
|
||||
* [5. Replace Nested Conditional with Guard Clauses (以卫语句取代嵌套条件表达式)](#5-replace-nested-conditional-with-guard-clauses-以卫语句取代嵌套条件表达式)
|
||||
* [6. Replace Conditional with Polymorphism (以多态取代条件表达式)](#6-replace-conditional-with-polymorphism-以多态取代条件表达式)
|
||||
* [7. Introduce Null Object(引入Null对象)](#7-introduce-null-object引入null对象)
|
||||
* [8. Introduce Assertion(引入断言)](#8-introduce-assertion引入断言)
|
||||
* [1. 分解条件表达式](#1-分解条件表达式)
|
||||
* [2. 合并条件表达式](#2-合并条件表达式)
|
||||
* [3. 合并重复的条件片段](#3-合并重复的条件片段)
|
||||
* [4. 移除控制标记](#4-移除控制标记)
|
||||
* [5. 以卫语句取代嵌套条件表达式](#5-以卫语句取代嵌套条件表达式)
|
||||
* [6. 以多态取代条件表达式](#6-以多态取代条件表达式)
|
||||
* [7. 引入Null对象](#7-引入null对象)
|
||||
* [8. 引入断言](#8-引入断言)
|
||||
* [九、简化函数调用](#九简化函数调用)
|
||||
* [1. Rename Method(函数改名)](#1-rename-method函数改名)
|
||||
* [2. Add Parameter(添加参数)](#2-add-parameter添加参数)
|
||||
* [3. Remove Parameter(移除参数)](#3-remove-parameter移除参数)
|
||||
* [4. Separate Query from Modifier(将查询函数和修改函数分离)](#4-separate-query-from-modifier将查询函数和修改函数分离)
|
||||
* [5. Parameterize Method(令函数携带参数)](#5-parameterize-method令函数携带参数)
|
||||
* [6. Replace Parameter with Explicit Methods(以明确函数取代参数)](#6-replace-parameter-with-explicit-methods以明确函数取代参数)
|
||||
* [7. Preserve Whole Object(保持对象完整)](#7-preserve-whole-object保持对象完整)
|
||||
* [8. Replace Parameter with Methods(以函数取代参数)](#8-replace-parameter-with-methods以函数取代参数)
|
||||
* [9. Introduce Parameter Object(引入参数对象)](#9-introduce-parameter-object引入参数对象)
|
||||
* [10. Remove Setting Method(移除设值函数)](#10-remove-setting-method移除设值函数)
|
||||
* [11. Hide Method(隐藏函数)](#11-hide-method隐藏函数)
|
||||
* [12. Replace Constructor with Factory Method (以工厂函数取代构造函数)](#12-replace-constructor-with-factory-method-以工厂函数取代构造函数)
|
||||
* [13. Encapsulate Downcast(封装向下转型)](#13-encapsulate-downcast封装向下转型)
|
||||
* [14. Replace Error Code with Exception (以异常取代错误码)](#14-replace-error-code-with-exception-以异常取代错误码)
|
||||
* [15. Replace Exception with Test(以测试取代异常)](#15-replace-exception-with-test以测试取代异常)
|
||||
* [1. 函数改名](#1-函数改名)
|
||||
* [2. 添加参数](#2-添加参数)
|
||||
* [3. 移除参数](#3-移除参数)
|
||||
* [4. 将查询函数和修改函数分离](#4-将查询函数和修改函数分离)
|
||||
* [5. 令函数携带参数](#5-令函数携带参数)
|
||||
* [6. 以明确函数取代参数](#6-以明确函数取代参数)
|
||||
* [7. 保持对象完整](#7-保持对象完整)
|
||||
* [8. 以函数取代参数](#8-以函数取代参数)
|
||||
* [9. 引入参数对象](#9-引入参数对象)
|
||||
* [10. 移除设值函数](#10-移除设值函数)
|
||||
* [11. 隐藏函数](#11-隐藏函数)
|
||||
* [12. 以工厂函数取代构造函数](#12-以工厂函数取代构造函数)
|
||||
* [13. 封装向下转型](#13-封装向下转型)
|
||||
* [14. 以异常取代错误码](#14-以异常取代错误码)
|
||||
* [15. 以测试取代异常](#15-以测试取代异常)
|
||||
* [十、处理概括关系](#十处理概括关系)
|
||||
* [1. Pull Up Field(字段上移)](#1-pull-up-field字段上移)
|
||||
* [2. Pull Up Method(函数上移)](#2-pull-up-method函数上移)
|
||||
* [3. Pull Up Constructor Body(构造函数本体上移)](#3-pull-up-constructor-body构造函数本体上移)
|
||||
* [4. Push Down Method(函数下移)](#4-push-down-method函数下移)
|
||||
* [5. Push Down Field(字段下移)](#5-push-down-field字段下移)
|
||||
* [6. Extract Subclass(提炼子类)](#6-extract-subclass提炼子类)
|
||||
* [7. Extract Superclass(提炼超类)](#7-extract-superclass提炼超类)
|
||||
* [8. Extract Interface(提炼接口)](#8-extract-interface提炼接口)
|
||||
* [9. Collapse Hierarchy(折叠继承体系)](#9-collapse-hierarchy折叠继承体系)
|
||||
* [10. Form Template Method(塑造模板函数)](#10-form-template-method塑造模板函数)
|
||||
* [11. Replace Inheritance with Delegation (以委托取代继承)](#11-replace-inheritance-with-delegation-以委托取代继承)
|
||||
* [12. Replace Delegation with Inheritance (以继承取代委托)](#12-replace-delegation-with-inheritance-以继承取代委托)
|
||||
* [1. 字段上移](#1-字段上移)
|
||||
* [2. 函数上移](#2-函数上移)
|
||||
* [3. 构造函数本体上移](#3-构造函数本体上移)
|
||||
* [4. 函数下移](#4-函数下移)
|
||||
* [5. 字段下移](#5-字段下移)
|
||||
* [6. 提炼子类](#6-提炼子类)
|
||||
* [7. 提炼超类](#7-提炼超类)
|
||||
* [8. 提炼接口](#8-提炼接口)
|
||||
* [9. 折叠继承体系](#9-折叠继承体系)
|
||||
* [10. 塑造模板函数](#10-塑造模板函数)
|
||||
* [11. 以委托取代继承](#11-以委托取代继承)
|
||||
* [12. 以继承取代委托](#12-以继承取代委托)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
|
@ -537,27 +537,37 @@ int discount (int inputVal, int quentity, int yearToDate){
|
|||
|
||||
# 六、在对象之间搬移特性
|
||||
|
||||
## 1. Move Method(搬移函数)
|
||||
## 1. 搬移函数
|
||||
|
||||
> Move Method
|
||||
|
||||
类中的某个函数与另一个类进行更多交流:调用后者或者被后者调用。
|
||||
|
||||
将这个函数搬移到另一个类中。
|
||||
|
||||
## 2. Move Field(搬移字段)
|
||||
## 2. 搬移字段
|
||||
|
||||
> Move Field
|
||||
|
||||
类中的某个字段被另一个类更多地用到,这里的用到是指调用取值设值函数,应当把该字段移到另一个类中。
|
||||
|
||||
## 3. Extract Class(提炼类)
|
||||
## 3. 提炼类
|
||||
|
||||
> Extract Class
|
||||
|
||||
某个类做了应当由两个类做的事。
|
||||
|
||||
应当建立一个新类,将相关的字段和函数从旧类搬移到新类。
|
||||
|
||||
## 4. Inline Class(将类内联化)
|
||||
## 4. 将类内联化
|
||||
|
||||
> Inline Class
|
||||
|
||||
与 Extract Class 相反。
|
||||
|
||||
## 5. Hide Delegate(隐藏“委托关系”)
|
||||
## 5. 隐藏委托关系
|
||||
|
||||
> Hide Delegate
|
||||
|
||||
建立所需的函数,隐藏委托关系。
|
||||
|
||||
|
@ -593,49 +603,67 @@ public Person getManager(){
|
|||
}
|
||||
```
|
||||
|
||||
## 6. Remove Middle Man(移除中间人)
|
||||
## 6. 移除中间人
|
||||
|
||||
> Remove Middle Man
|
||||
|
||||
与 Hide Delegate 相反,本方法需要移除委托函数,让客户直接调用委托类。
|
||||
|
||||
Hide Delegate 有很大好处,但是它的代价是:每当客户要使用受托类的新特性时,就必须在服务器端添加一个简单的委托函数。随着受委托的特性越来越多,服务器类完全变成了一个“中间人”。
|
||||
|
||||
## 7. Introduce Foreign Method(引入外加函数)
|
||||
## 7. 引入外加函数
|
||||
|
||||
> Introduce Foreign Method
|
||||
|
||||
需要为提供服务的类添加一个函数,但是无法修改这个类。
|
||||
|
||||
可以在客户类中建立一个函数,并以第一参数形式传入一个服务类的实例,让客户类组合服务器实例。
|
||||
|
||||
## 8. Introduce Local Extension(引入本地扩展)
|
||||
## 8. 引入本地扩展
|
||||
|
||||
> Introduce Local Extension
|
||||
|
||||
和 Introduce Foreign Method 目的一样,但是 Introduce Local Extension 通过建立新的类来实现。有两种方式:子类或者包装类,子类就是通过继承实现,包装类就是通过组合实现。
|
||||
|
||||
# 七、重新组织数据
|
||||
|
||||
## 1. Self Encapsulate Field(自封装字段)
|
||||
## 1. 自封装字段
|
||||
|
||||
> Self Encapsulate Field
|
||||
|
||||
为字段建立取值/设值函数,并用这些函数来访问字段。只有当子类想访问超类的一个字段,又想在子类中将对这个字段访问改为一个计算后的值,才使用这种方式,否则直接访问字段的方式简洁明了。
|
||||
|
||||
## 2. Replace Data Value with Object(以对象取代数据值)
|
||||
## 2. 以对象取代数据值
|
||||
|
||||
> Replace Data Value with Object
|
||||
|
||||
在开发初期,往往会用简单的数据项表示简单的情况,但是随着开发的进行,一些简单数据项会具有一些特殊行为。比如一开始会把电话号码存成字符串,但是随后发现电话号码需要“格式化”、“抽取区号”之类的特殊行为。
|
||||
|
||||
## 3. Change Value to Reference(将值对象改成引用对象)
|
||||
## 3. 将值对象改成引用对象
|
||||
|
||||
> Change Value to Reference
|
||||
|
||||
将彼此相等的实例替换为同一个对象。这就要用一个工厂来创建这种唯一对象,工厂类中需要保留一份已经创建对象的列表,当要创建一个对象时,先查找这份列表中是否已经存在该对象,如果存在,则返回列表中的这个对象;否则,新建一个对象,添加到列表中,并返回该对象。
|
||||
|
||||
## 4. Change Reference to value(将引用对象改为值对象)
|
||||
## 4. 将引用对象改为值对象
|
||||
|
||||
> Change Reference to value
|
||||
|
||||
以 Change Value to Reference 相反。值对象有个非常重要的特性:它是不可变的,不可变表示如果要改变这个对象,必须用一个新的对象来替换旧对象,而不是修改旧对象。
|
||||
|
||||
需要为值对象实现 equals() 和 hashCode() 方法
|
||||
|
||||
## 5. Replace Array with Object(以对象取代数组)
|
||||
## 5. 以对象取代数组
|
||||
|
||||
> Replace Array with Object
|
||||
|
||||
有一个数组,其中的元素各自代表不同的东西。
|
||||
|
||||
以对象替换数组,对于数组中的每个元素,以一个字段来表示,这样方便操作,也更容易理解。
|
||||
|
||||
## 6. Duplicate Observed Data(赋值“被监视数据”)
|
||||
## 6. 赋值被监视数据
|
||||
|
||||
> Duplicate Observed Data
|
||||
|
||||
一些领域数据置身于 GUI 控件中,而领域函数需要访问这些数据。
|
||||
|
||||
|
@ -643,7 +671,9 @@ Hide Delegate 有很大好处,但是它的代价是:每当客户要使用受
|
|||
|
||||
<div align="center"> <img src="../pics//e024bd7e-fb4e-4239-9451-9a6227f50b00.jpg"/> </div><br>
|
||||
|
||||
## 7. Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
|
||||
## 7. 将单向关联改为双向关联
|
||||
|
||||
> Change Unidirectional Association to Bidirectional
|
||||
|
||||
当两个类都需要对方的特性时,可以使用双向关联。
|
||||
|
||||
|
@ -674,39 +704,55 @@ class Curstomer{
|
|||
|
||||
注意到,这里让 Curstomer 类来控制关联关系。有以下原则来决定哪个类来控制关联关系:如果某个对象是组成另一个对象的部件,那么由后者负责控制关联关系;如果是一对多关系,则由单一引用那一方来控制关联关系。
|
||||
|
||||
## 8. Change Bidirectional Association to Unidirectional(将双向关联改为单向关联)
|
||||
## 8. 将双向关联改为单向关联
|
||||
|
||||
> Change Bidirectional Association to Unidirectional
|
||||
|
||||
和 Change Unidirectional Association to Bidirectiona 为反操作。
|
||||
|
||||
双向关联维护成本高,并且也不易于理解。大量的双向连接很容易造成“僵尸对象”:某个对象本身已经死亡了,却保留在系统中,因为它的引用还没有全部完全清除。
|
||||
|
||||
## 9. Replace Magic Number with Symbolic Constant(以字面常量取代魔法数)
|
||||
## 9. 以字面常量取代魔法数
|
||||
|
||||
> Replace Magic Number with Symbolic Constant
|
||||
|
||||
创建一个常量,根据其意义为它命名,并将字面常量换位这个常量。
|
||||
|
||||
## 10. Encapsulate Field(封装字段)
|
||||
## 10. 封装字段
|
||||
|
||||
> Encapsulate Field
|
||||
|
||||
public 字段应当改为 private,并提供相应的访问函数。
|
||||
|
||||
## 11. Encapsulate Collection(封装集合)
|
||||
## 11. 封装集合
|
||||
|
||||
> Encapsulate Collection
|
||||
|
||||
函数返回集合的一个只读副本,并在这个类中提供添加/移除集合元素的函数。如果函数返回集合自身,会让用户得以修改集合内容而集合拥有者却一无所知。
|
||||
|
||||
## 12. Replace Record with Data Class(以数据类取代记录)
|
||||
## 12. 以数据类取代记录
|
||||
|
||||
## 13. Replace Type Code with Class(以类取代类型码)
|
||||
> Replace Record with Data Class
|
||||
|
||||
## 13. 以类取代类型码
|
||||
|
||||
> Replace Type Code with Class
|
||||
|
||||
类中有一个数值类型码,但它并不影响类的行为,就用一个新类替换该数值类型码。如果类型码出现在 switch 语句中,需要使用 Replace Conditional with Polymorphism 去掉 switch,首先必须运用 Replace Type Code with Subcalss 或 Replace Type Code with State/Strategy 去掉类型码。
|
||||
|
||||
<div align="center"> <img src="../pics//27c2e0b3-8f95-453d-bedc-6398a8566ce9.jpg"/> </div><br>
|
||||
|
||||
## 14. Replace Type Code with Subcalsses(以子类取代类型码)
|
||||
## 14. 以子类取代类型码
|
||||
|
||||
> Replace Type Code with Subcalsses
|
||||
|
||||
有一个不可变的类型码,它会影响类的行为,以子类取代这个类型码。
|
||||
|
||||
<div align="center"> <img src="../pics//c41d3977-e0e7-4ee4-93e1-d84f1ae3e20e.jpg"/> </div><br>
|
||||
|
||||
## 15. Replace Type Code with State/Strategy (以 State/Strategy 取代类型码)
|
||||
## 15. 以 State/Strategy 取代类型码
|
||||
|
||||
> Replace Type Code with State/Strategy
|
||||
|
||||
有一个可变的类型码,它会影响类的行为,以状态对象取代类型码。
|
||||
|
||||
|
@ -714,7 +760,9 @@ public 字段应当改为 private,并提供相应的访问函数。
|
|||
|
||||
<div align="center"> <img src="../pics//81fd1d6f-a3b2-4160-9a0a-1f7cb50ba440.jpg"/> </div><br>
|
||||
|
||||
## 16. Replace Subclass with Fields(以字段取代子类)
|
||||
## 16. 以字段取代子类
|
||||
|
||||
> Replace Subclass with Fields
|
||||
|
||||
各个子类的唯一差别只在“返回常量数据”的函数上。
|
||||
|
||||
|
@ -722,7 +770,9 @@ public 字段应当改为 private,并提供相应的访问函数。
|
|||
|
||||
# 八、简化条件表达式
|
||||
|
||||
## 1. Decompose Conditional(分解条件表达式)
|
||||
## 1. 分解条件表达式
|
||||
|
||||
> Decompose Conditional
|
||||
|
||||
对于一个复杂的条件语句,可以从 if、then、else 三个段落中分别提炼出独立函数。
|
||||
|
||||
|
@ -738,7 +788,9 @@ if(notSummer(date))
|
|||
else charge = summerCharge(quantity);
|
||||
```
|
||||
|
||||
## 2. Consolidate Conditional Expression(合并条件表达式)
|
||||
## 2. 合并条件表达式
|
||||
|
||||
> Consolidate Conditional Expression
|
||||
|
||||
有一系列条件测试,都得到相同结果。
|
||||
|
||||
|
@ -759,7 +811,9 @@ double disabilityAmount(){
|
|||
}
|
||||
```
|
||||
|
||||
## 3. Consolidate Duplicate Conditional Fragments (合并重复的条件片段)
|
||||
## 3. 合并重复的条件片段
|
||||
|
||||
> Consolidate Duplicate Conditional Fragments
|
||||
|
||||
在条件表达式的每个分支上有着相同的一段代码。
|
||||
|
||||
|
@ -784,13 +838,17 @@ if (isSpecialDeal()) {
|
|||
send();
|
||||
```
|
||||
|
||||
## 4. Remove Control Flag(移除控制标记)
|
||||
## 4. 移除控制标记
|
||||
|
||||
> Remove Control Flag
|
||||
|
||||
在一系列布尔表达式中,某个变量带有“控制标记”的作用。
|
||||
|
||||
用 break语 句或 return 语句来取代控制标记。
|
||||
|
||||
## 5. Replace Nested Conditional with Guard Clauses (以卫语句取代嵌套条件表达式)
|
||||
## 5. 以卫语句取代嵌套条件表达式
|
||||
|
||||
> Replace Nested Conditional with Guard Clauses
|
||||
|
||||
如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回,这样的单独检查常常被称为“卫语句”(guard clauses)。
|
||||
|
||||
|
@ -820,7 +878,9 @@ double getPayAmount() {
|
|||
};
|
||||
```
|
||||
|
||||
## 6. Replace Conditional with Polymorphism (以多态取代条件表达式)
|
||||
## 6. 以多态取代条件表达式
|
||||
|
||||
> Replace Conditional with Polymorphism
|
||||
|
||||
将这个条件表达式的每个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数。需要先使用 Replace Type Code with Subclass 或 Replace Type Code with State/Strategy 来建立继承结果。
|
||||
|
||||
|
@ -840,7 +900,9 @@ double getSpeed() {
|
|||
|
||||
<div align="center"> <img src="../pics//1c8432c8-2552-457f-b117-1da36c697221.jpg"/> </div><br>
|
||||
|
||||
## 7. Introduce Null Object(引入Null对象)
|
||||
## 7. 引入Null对象
|
||||
|
||||
> Introduce Null Object
|
||||
|
||||
将 null 值替换为 null 对象。这样做的好处在于,不需要询问对象是否为空,直接调用就行。
|
||||
|
||||
|
@ -849,7 +911,9 @@ if (customer == null) plan = BillingPlan.basic();
|
|||
else plan = customer.getPlan();
|
||||
```
|
||||
|
||||
## 8. Introduce Assertion(引入断言)
|
||||
## 8. 引入断言
|
||||
|
||||
> Introduce Assertion
|
||||
|
||||
以断言明确表现某种假设。断言只能用于开发过程中,产品代码中不会有断言。
|
||||
|
||||
|
@ -869,19 +933,27 @@ double getExpenseLimit() {
|
|||
|
||||
# 九、简化函数调用
|
||||
|
||||
## 1. Rename Method(函数改名)
|
||||
## 1. 函数改名
|
||||
|
||||
> Rename Method
|
||||
|
||||
使函数名能解释函数的用途。
|
||||
|
||||
## 2. Add Parameter(添加参数)
|
||||
## 2. 添加参数
|
||||
|
||||
> Add Parameter
|
||||
|
||||
使函数不需要通过调用获得某个信息。
|
||||
|
||||
## 3. Remove Parameter(移除参数)
|
||||
## 3. 移除参数
|
||||
|
||||
> Remove Parameter
|
||||
|
||||
与 Add Parameter 相反,改用调用的方式来获得某个信息。
|
||||
|
||||
## 4. Separate Query from Modifier(将查询函数和修改函数分离)
|
||||
## 4. 将查询函数和修改函数分离
|
||||
|
||||
> Separate Query from Modifier
|
||||
|
||||
某个函数即返回对象状态值,又修改对象状态。
|
||||
|
||||
|
@ -896,7 +968,9 @@ getTotalOutstanding();
|
|||
setReadyForSummaries();
|
||||
```
|
||||
|
||||
## 5. Parameterize Method(令函数携带参数)
|
||||
## 5. 令函数携带参数
|
||||
|
||||
> Parameterize Method
|
||||
|
||||
若干函数做了类似的工作,但在函数本体中却包含了不同的值。
|
||||
|
||||
|
@ -910,7 +984,9 @@ tenPercentRaise();
|
|||
raise(percentage);
|
||||
```
|
||||
|
||||
## 6. Replace Parameter with Explicit Methods(以明确函数取代参数)
|
||||
## 6. 以明确函数取代参数
|
||||
|
||||
> Replace Parameter with Explicit Methods
|
||||
|
||||
有一个函数,完全取决于参数值而采取不同行为。
|
||||
|
||||
|
@ -939,7 +1015,9 @@ void setWidth(int arg){
|
|||
}
|
||||
```
|
||||
|
||||
## 7. Preserve Whole Object(保持对象完整)
|
||||
## 7. 保持对象完整
|
||||
|
||||
> Preserve Whole Object
|
||||
|
||||
从某个对象中取出若干值,将它们作为某一次函数调用时的参数。
|
||||
|
||||
|
@ -955,7 +1033,9 @@ withinPlan = plan.withinRange(low,high);
|
|||
withinPlan = plan.withinRange(daysTempRange());
|
||||
```
|
||||
|
||||
## 8. Replace Parameter with Methods(以函数取代参数)
|
||||
## 8. 以函数取代参数
|
||||
|
||||
> Replace Parameter with Methods
|
||||
|
||||
对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能够调用前一个函数。
|
||||
|
||||
|
@ -972,7 +1052,9 @@ int basePrice = _quantity * _itemPrice;
|
|||
double finalPrice = discountedPrice (basePrice);
|
||||
```
|
||||
|
||||
## 9. Introduce Parameter Object(引入参数对象)
|
||||
## 9. 引入参数对象
|
||||
|
||||
> Introduce Parameter Object
|
||||
|
||||
某些参数总是很自然地同时出现,这些参数就是 Data Clumps。
|
||||
|
||||
|
@ -980,25 +1062,33 @@ double finalPrice = discountedPrice (basePrice);
|
|||
|
||||
<div align="center"> <img src="../pics//08738dd0-ae8e-404a-ba78-a6b1b7d225b3.jpg"/> </div><br>
|
||||
|
||||
## 10. Remove Setting Method(移除设值函数)
|
||||
## 10. 移除设值函数
|
||||
|
||||
> Remove Setting Method
|
||||
|
||||
类中的某个字段应该在对象创建时被设值,然后就不再改变。
|
||||
|
||||
去掉该字段的所有设值函数,并将该字段设为 final。
|
||||
|
||||
## 11. Hide Method(隐藏函数)
|
||||
## 11. 隐藏函数
|
||||
|
||||
> Hide Method
|
||||
|
||||
有一个函数,从来没有被其他任何类用到。
|
||||
|
||||
将这个函数修改为 private。
|
||||
|
||||
## 12. Replace Constructor with Factory Method (以工厂函数取代构造函数)
|
||||
## 12. 以工厂函数取代构造函数
|
||||
|
||||
> Replace Constructor with Factory Method
|
||||
|
||||
希望在创建对象时不仅仅是做简单的建构动作。
|
||||
|
||||
将构造函数替换为工厂函数。
|
||||
|
||||
## 13. Encapsulate Downcast(封装向下转型)
|
||||
## 13. 封装向下转型
|
||||
|
||||
> Encapsulate Downcast
|
||||
|
||||
某个函数返回的对象,需要由函数调用者执行向下转型(downcast)。
|
||||
|
||||
|
@ -1015,13 +1105,17 @@ Reading lastReading(){
|
|||
}
|
||||
```
|
||||
|
||||
## 14. Replace Error Code with Exception (以异常取代错误码)
|
||||
## 14. 以异常取代错误码
|
||||
|
||||
> Replace Error Code with Exception
|
||||
|
||||
某个函数返回一个特定的代码,用以表示某种错误情况。
|
||||
|
||||
改用异常,异常将普通程序和错误处理分开,使代码更容易理解。
|
||||
|
||||
## 15. Replace Exception with Test(以测试取代异常)
|
||||
## 15. 以测试取代异常
|
||||
|
||||
> Replace Exception with Test
|
||||
|
||||
面对一个调用者可以预先检查的条件,你抛出了一个异常。
|
||||
|
||||
|
@ -1044,19 +1138,25 @@ double getValueForPeriod(int periodNumber) {
|
|||
|
||||
# 十、处理概括关系
|
||||
|
||||
## 1. Pull Up Field(字段上移)
|
||||
## 1. 字段上移
|
||||
|
||||
> Pull Up Field
|
||||
|
||||
两个子类拥有相同的字段。
|
||||
|
||||
将该字段移至超类。
|
||||
|
||||
## 2. Pull Up Method(函数上移)
|
||||
## 2. 函数上移
|
||||
|
||||
> Pull Up Method
|
||||
|
||||
有些函数,在各个子类中产生完全相同的结果。
|
||||
|
||||
将该函数移至超类。
|
||||
|
||||
## 3. Pull Up Constructor Body(构造函数本体上移)
|
||||
## 3. 构造函数本体上移
|
||||
|
||||
> Pull Up Constructor Body
|
||||
|
||||
你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。
|
||||
|
||||
|
@ -1079,55 +1179,73 @@ public Manager(String name, String id, int grade) {
|
|||
}
|
||||
```
|
||||
|
||||
## 4. Push Down Method(函数下移)
|
||||
## 4. 函数下移
|
||||
|
||||
> Push Down Method
|
||||
|
||||
超类中的某个函数只与部分子类有关。
|
||||
|
||||
将这个函数移到相关的那些子类去。
|
||||
|
||||
## 5. Push Down Field(字段下移)
|
||||
## 5. 字段下移
|
||||
|
||||
> Push Down Field
|
||||
|
||||
超类中的某个字段只被部分子类用到。
|
||||
|
||||
将这个字段移到需要它的那些子类去。
|
||||
|
||||
## 6. Extract Subclass(提炼子类)
|
||||
## 6. 提炼子类
|
||||
|
||||
> Extract Subclass
|
||||
|
||||
类中的某些特性只被某些实例用到。
|
||||
|
||||
新建一个子类,将上面所说的那一部分特性移到子类中。
|
||||
|
||||
## 7. Extract Superclass(提炼超类)
|
||||
## 7. 提炼超类
|
||||
|
||||
> Extract Superclass
|
||||
|
||||
两个类有相似特性。
|
||||
|
||||
为这两个类建立一个超类,将相同特性移至超类。
|
||||
|
||||
## 8. Extract Interface(提炼接口)
|
||||
## 8. 提炼接口
|
||||
|
||||
> Extract Interface
|
||||
|
||||
若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。
|
||||
|
||||
将相同的子集提炼到一个独立接口中。
|
||||
|
||||
## 9. Collapse Hierarchy(折叠继承体系)
|
||||
## 9. 折叠继承体系
|
||||
|
||||
> Collapse Hierarchy
|
||||
|
||||
超类和子类之间无太大区别。
|
||||
|
||||
将它们合为一体。
|
||||
|
||||
## 10. Form Template Method(塑造模板函数)
|
||||
## 10. 塑造模板函数
|
||||
|
||||
> Form Template Method
|
||||
|
||||
你有一些子类,其中相应的某些函数以相同顺序执行类似的操作,但各个操作的细节上有所不同。
|
||||
|
||||
将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同了。然后将原函数上移至超类。(模板方法模式)
|
||||
|
||||
## 11. Replace Inheritance with Delegation (以委托取代继承)
|
||||
## 11. 以委托取代继承
|
||||
|
||||
> Replace Inheritance with Delegation
|
||||
|
||||
某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。
|
||||
|
||||
在子类中新建一个字段用以保存超类,调整子类函数,令它改而委托超类,然后去掉两者之间的继承关系。
|
||||
|
||||
## 12. Replace Delegation with Inheritance (以继承取代委托)
|
||||
## 12. 以继承取代委托
|
||||
|
||||
> Replace Delegation with Inheritance
|
||||
|
||||
你在两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数。
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user