本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42549977
在上一篇文章中介绍了“移除对参数的赋值“。本文将介绍“以函数对象取代函数”这种重构手法。
下面让我们来学习这种重构手法吧。
发现:你有一个大型函数,其中对局部变量的使用使你无法采用“提炼函数”这种重构手法。
解决:将这个函数放进一个单独对象中,这样,局部变量就成了对象的字段,然后就可以在同一个对象中将这个大型函数分解为多个小型函数。
//重构前
class Order....
double price(){
double basePrice;
double secondaryPrice;
double thirdaryPrice;
//compute()
......
}<
//重构后
class Order...
double price(){
return new PriceCalculator(this).compute();
}
class PriceCalculator{
double basePrice;
double secondaryPrice;
double thirdaryPrice;
double compute(){
//...
}
}
在前面的文章中一直在强调小型函数的优美动人。只要将相对独立的代码从大函数提炼出来,就可以大大提高代码的可读性。
但是,局部变量的存在会增加函数分解的难度。如果一个函数中的局部变量泛滥成灾,那么想分解这个函数是非常困难的。“以查询替换临时变量”手法可以帮助减轻负担,但有时候还是会发现根本无法拆解一个需要拆解的函数。这种情况就应该考虑使用函数对象来解决。本文的重构方法会将所有的局部变量都变成函数对象的字段。然后就可以使用“提炼函数”创造新的函数,从而将原来的大型函数拆解变小。
class Account{
int gamm(int value, int quantity, int year2Date){
int importValue1 = (value * quantity) + delta();
int importValue2 = (value * year2Date) + 200;
if(year2Date - importValue1 >200)
importValue2-=50;
int importValue3 = importValue2 * 8;
//......
return importValue3 - 2 * importValue1;
}
//.....
}
为了把这个函数变为函数对象,首先需要声明一个新类。在新类中提供final对象保存原对象,对于函数的每个参数和每个临时变量,也以一个字段逐一保留。
class Gamm{
private final Account _account;
private int value;
private int quantity;
private int year2Date;
private int importValue1;
private int importValue2;
private int importValue3;
接下来,加入一个构造函数。 Gamm(Account source, int inputVal, int quantity, int year2Date){
this._account = source;
this.value = inputVal;
this.quantity = quantity;
this.year2Date = year2Date;
}
现在可以把原本函数搬到compute()中了。函数中任何调用Accout类的地方,都必改用_account字段。
int compute(){
importValue1 = (value * quantity) + _account.delta();
importValue2 = (value * year2Date) + 200;
if(year2Date - importValue1 >200)
importValue2-=50;
importValue3 = importValue2 * 8;
//......
return importValue3 - 2 * importValue1;
}
然后,修改旧函数,让它将工作委托给刚完成的这个函数对象。
int gamm(int value, int quantity, int year2Date){
return new Gamm(this,value,quantity,year2Date).compute();
}
以上就是本文重构方法的基本原则。其所带来的好处是:现在可以轻松地对compute()函数采取“提炼函数”,而不必担心参数传递的问题。
//运用提炼函数 不必担心参数问题
int compute(){
importValue1 = (value * quantity) + _account.delta();
importValue2 = (value * year2Date) + 200;
importantThing();
importValue3 = importValue2 * 8;
//......
return importValue3 - 2 * importValue1;
}
private void importantThing() {
if(year2Date - importValue1 >200)
importValue2-=50;
}
重构笔记——入门篇
重构笔记——代码的坏味道(上)
重构笔记——代码的坏味道(下)
重构笔记——构筑测试体
重构笔记——提炼函数
重构笔记——内联函数
重构笔记——内联临时变量
重构笔记——以查询取代临时变量
重构笔记——引入解释性变量
重构笔记——分解临时变量
重构笔记——移除对参数的赋值