你有一个大型函数,函数中使用了许多的局部变量,使你无法釆用 Extract Method提炼函数
手法重构,那么使用以函数对象取代函数
手法将处理函数中的局部变量,然后在对函数做 Extract Method提炼函数
重构。
只要将相对独立的代码从大型函数中提炼出来,放到小型函数就可以大大提高代码的可读性。
但是,函数内局部变量的存在会增加函数分解难度。如果一个函数之中局部变量泛滥成灾, 那么想分解这个函数是非常困难的。
以函数对象取代函数
会将所有局部变量都变成函数对象(method object)的值域(field)。然后你就可以对这个新对象使用 Extract Method提炼函数
创造出新函数,从而将原本的大型函数拆解变短。
final
字段,用以保存原先大型函数所在的对象。我们将这个字段称为“源对象”。同时,针对原函数的每个临时变量和每个参数,在新类中建立一个对应的字段保存之。compute()函数
。这个实例的逻辑不需要关心,只需要观察它重构的过程。
Class Accountint gamma (int inputVal, int quantity, int yearToDate) {int importantValue1 = (inputVal * quantity) + delta();int importantValue2 = (inputVal * yearToDate) + 100;if ((yearToDate - importantValue1) > 100)importantValue2 -= 20;int importantValue3 = importantValue2 * 7;// and so on.return importantValue3 - 2 * importantValue1;}
为了把这个函数变成一个函数对象(method object),我首先需要声明一个新class。
在此新class中我应该提供一个final值变量用以保存原先对象(源对象);
对于函数的每一个参数和每一个临时变量,也以一个个值域逐一保存。
class Gamma...private final Account _account;private int inputVal;private int quantity;private int yearToDate;private int importantValue1;private int importantValue2;private int importantValue3;
按惯例,我通常会以下划线作为值域名称的前缀。但为了保持小步前进,我暂时先保留这些值域的原名。
接下来,加入一个构造函数
// 创建构造器,接收原函数的对象和参数
Gamma (Account source, int inputValArg, int quantityArg, int yearToDateArg) {// 将调用原函数的对象和函数参数 赋值给新类的属性_account = source;inputVal = inputValArg;quantity = quantityArg;yearToDate = yearToDateArg;
}
现在可以把原本的函数搬到compute()了。函数中任何调用Account class
的地方,我都必须改而使用_account值域:
// 将原函数代码拷贝到新函数中
int compute () {importantValue1 = (inputVal * quantity) + _account.delta();importantValue2 = (inputVal * yearToDate) + 100;if ((yearToDate - importantValue1) > 100)importantValue2 -= 20;int importantValue3 = importantValue2 * 7;// and so on.return importantValue3 - 2 * importantValue1;
}
然后修改原函数,让他调用新类中的compute()
方法
// 原函数调用新类中的方法
int gamma (int inputVal, int quantity, int yearToDate) {return new Gamma(this, inputVal, quantity, yearToDate).compute();
}
这就是本项重构的基本原则。它带来的好处是:现在我可以轻松地对compute()函数采取 Extract Method提炼函数
,不必担心引数(argument)传递。
int compute () {importantValue1 = (inputVal * quantity) + _account.delta();importantValue2 = (inputVal * yearToDate) + 100;// 使用提炼函数importantThing();int importantValue3 = importantValue2 * 7;// and so on.return importantValue3 - 2 * importantValue1;}// 提炼函数void importantThing() {if ((yearToDate - importantValue1) > 100)importantValue2 -= 20;}