本系列来自《java 重构改善既有代码的设计》一书
如:将一个临时变量temp保存到某一个表达式的运行结果。
做法将这个表达式提炼到一个独立函数(所谓查询式:Query),将这个临时变量的所有替换为新函数的调用。新函数可以被其它地方引用。
public double getPrice(){
double basePrice = itemPrice * quantity;
if(basePrice > 1000) {
return basePrice * 0.95;
} else {
return basePrice * 0.98;
}
}
可以写成:
public double getPrice() {
if (basePrice() > 1000) {
return basePrice() * 0.95;
} else {
return basePrice() * 0.98;
}
}
public double basePrice() {
return itemPrice * quantity;
}
考虑到临时变量只是暂时的,而且只能在所属函数内部使用,由于临时变量只有在所属函数内部使用,所以会驱使你写出更长的函数,因为只有这样你才能访问到要访问的临时变量。而如果把临时变量替换成为一个查询式(query method),那么同一个类的所有函数都能获取这份信息。
以查询替换临时变量往往是提炼方法(Extract Method)前必不可少的步骤,因为局部变量会让代码难以提炼,所以应该尽可能把他们替换成查询式。
做法:
1、找出只被赋值一次的临时变量(如果某个变量被赋值超过一次,考虑使用Split Temppopary Variable(解剖临时变量)将它分解成多个变量)。
2、将该变量申明为final(final只能被赋值一次)
3、编译(可以确保该临时变量确实只被赋值一次)。
4、将对该临时变量赋值的语句等号右侧部分提炼到一个独立的函数中(首先将它申明为private,如果后续有其他class需要调用,可以取消保护。同时要确保提炼出来的函数无任何连接影响,即该函数并不修改任何对象的内容)。
5、编译测试,并在临时变量上实施Inline Temp。
例:
public double getPrice() {
int basePrice = quantity * itemPrice;
double discountFactor;
if (basePrice() > 1000) {
discountFactor = 0.95;
} else {
discountFactor = 0.98;
}
return basePrice * discountFactor;
}
尽管代码十分清楚,依然将临时变量加上final,检查他们是否的确只被赋值一次。然后编译运行,这样处理的话如果没有问题,编译器就不会警告。之所以这样,是因为如果这个变量不只被赋值一次,那么我们就不能进行这次重构。
接下来就是提炼Query Method:
public double getPrice() {
final int basePrice = basePrice();
final double discountFactor;
if (basePrice() > 1000) {
discountFactor = 0.95;
} else {
discountFactor = 0.98;
}
return basePrice() * discountFactor;
}
private int basePrice() {
return itemPrice * quantity;
}
接下来将临时变量内联化,删除临时变量:
public double getPrice() {
final double discountFactor;
if (basePrice() > 1000) {
discountFactor = 0.95;
} else {
discountFactor = 0.98;
}
return basePrice() * discountFactor;
}
同样的道理,提取discountFactor的Query Method
public double getPrice() {
return basePrice() * discountFactor();
}
private int basePrice() {
return itemPrice * quantity;
}
private double discountFactor() {
if (basePrice() > 1000) {
return 0.95;
}
return 0.98;
}
这是我们发现:如果没有将basePrice替换成一个查询表达式,将多么难提炼discountFactor().