文章目录
- 读书笔记 -《重构-改善既有代码的设计》Part4
- 简化函数调用
- Rename Method
- Add Parameter
- Remove Parameter
- Separate Query from Modifier
- Replace Parameter with Explicit Methods
- Preserve Whole Object
- Replace Parameter with Methods
- Introduce Parameter Object
- Remove Setting Method
- Hide Method
- Replace Constructor with Factory Method
- Encapsulate Downcast
- Replace Error Code with Exception
- Replace Exception with Test
- 处理概括关系(继承体系)
上一节 读书笔记 -《重构-改善既有代码的设计》Part3
读书笔记 -《重构-改善既有代码的设计》Part4
简化函数调用
Rename Method
如果函数的名称不能明确函数的用途,需修改函数名称
Add Parameter
函数如果需要从调用端获取更多参数,则通过 Introduce Method Object 手段,引入对象参数
Remove Parameter
如果函数不再需要某个参数,应该删除这个参数
Separate Query from Modifier
将查询函数和修改函数分离
某个函数既返回对象状态值,又修改对象状态,需要建立两个不同的函数,一个负责查询,一个负责修改
容易引发并发问题
Parameterize Method
发现两个函数都在做类似的工作,可能只有少数值不同,他们的行为不同,我们可以考虑合并这个函数,提取这些值作为参数,让分离的函数统一起来
Replace Parameter with Explicit Methods
以明确的函数取代参数
void setValue(int type, int val) {
if (type == WIDTH_TYPE) {
this.width = val;
} else if (type == HEIGHT_TYPE) {
this.height = val;
}
}
=>
void setWidth(int width) {
this.width = width;
}
void setHeight(int height) {
this.height = height;
}
Preserve Whole Object
保持对象完整
从某个对象中取出若干值,将它们作为某一次函数调用时的参数,改为传递整个对象
class Rectangle {
private int width;
private int height;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getArea() {
return width * height;
}
}
int widht = rect.getWidth();
int height = rect.getHeight();
areaOk = IsOk(width, height);
=>
areaOk = IsOk(rect);
Replace Parameter with Methods
以函数取代参数
对象调用某个函数,并将所得结果作为参数,传递给另一个函数。
而接受该参数的函数本身也能够调用前一个函数。
则让参数接受者去掉该项参数,并直接调用前一个函数。
call A() -> get param
call B(param) -> get result
B() can call A() -> then B() { param = A() ...} -> get result
Introduce Parameter Object
引入参数对象,用对象参数取代各个分散的参数
Remove Setting Method
移除设值参数
类中的某个字段在对象创建时被设置,然后不再改变,那么去掉该字段的所有设值函数
Hide Method
有一个函数,从来没有被其它任何类用到,那么应该设置这个函数为 private
Replace Constructor with Factory Method
工厂方法取代构造函数
比如常见的根据类型码返回不同的类型对象,而这些类型继承自一个超类
Encapsulate Downcast
封装向下转型
某个函数返回的对象,需要由函数调用者执行向下转型(downcast)
则将向下转型动作移到函数中
Object lastReading() {
return readings.lastElement();
}
=>
Reading lastReading() {
return (Reading)readings.lastElement();
}
Replace Error Code with Exception
以异常取代错误码
某个函数返回一个特定的错误码,则改用抛出异常
int withdraw(int amount) {
if (amount > _balance) {
return -1;
} else {
_balance -= amount;
return 0;
}
}
=>
void withdraw(int amount) throws BalanceException {
if (amount > _balance) {
throws new BalanceException();
}
_balance -= amount;
}
非受控异常 => 调用者负责检查,抛出异常,可以在测试中发现问题
受控异常 => 首先要有一个异常类,通过 try … catch 控制异常
Replace Exception with Test
面对一个调用者可以预先检查的条件,你跑出了一个异常。
=> 修改调用者,使它在调用函数之前做检查
double getValueForPeriod(int periodNumber) {
try {
return ...
} catch(...) {
return 0;
}
}
=>
double getValueForPeriod(int periodNumber) {
if (...) return 0;
return ...
}
处理概括关系(继承体系)
Pull Up Filed
child filed -> parent filed
Pull Up Method
child method-> parent method
Pull Up Constructor Body
各个子类中拥有一些构造函数,几乎一致,可在超类中新建一个构造函数,子类中调用它
Push Down Method
超类中的某个函数与部分子类有关,将这个函数移到相关的那些子类中去
Push Down Field
超类中的某个字段与部分子类有关,将这个字段移到相关的那些子类中去
Extract Subclass
类中的某些特性只被某些实例用到,新建一个子类,将这些特性移到子类中
Extract Superclass
两个类相似特性,可以提取超类
Extract Interface
若干客户实用类接口中的同一子集,或者两个类的接口有部分相同,新建一个独立接口,将子集提炼到接口中
Collapse Hierarchy
超类和子类并无太大区别,合并它们
Form Template Method
使用模板函数编程会带来意想不到的便利
你有一些子类,其中相应的某些函数以相同顺序执行类似的操作,但各个操作的细节上有所不同。将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同了。然后将苑函数上移至超类。
Replace Inheritance with Delegation
以委托取代继承
我们在上面的记录中,已有对这部分有讲解
Replace Delegation with Inheritance
两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数
让委托类继承受妥类
Employee -> getName()
Person -> getName()
=>
Employee extends Person