重构函数-Replace Method with Method Object以函数对象取代函数八
创始人
2025-05-29 09:25:58

重构函数-Replace Method with Method Object以函数对象取代函数八

1.以函数对象取代函数

1.1.使用场景

你有一个大型函数,函数中使用了许多的局部变量,使你无法釆用 Extract Method提炼函数 手法重构,那么使用以函数对象取代函数手法将处理函数中的局部变量,然后在对函数做 Extract Method提炼函数 重构。

1.2.使用动机

只要将相对独立的代码从大型函数中提炼出来,放到小型函数就可以大大提高代码的可读性。
但是,函数内局部变量的存在会增加函数分解难度。如果一个函数之中局部变量泛滥成灾, 那么想分解这个函数是非常困难的。

以函数对象取代函数会将所有局部变量都变成函数对象(method object)的值域(field)。然后你就可以对这个新对象使用 Extract Method提炼函数 创造出新函数,从而将原本的大型函数拆解变短。

1.3.如何使用

  • 建立一个新类,根据待处理函数的用途,为这个类命名。
  • 在新类中建立一个final字段,用以保存原先大型函数所在的对象。我们将这个字段称为“源对象”。同时,针对原函数的每个临时变量和每个参数,在新类中建立一个对应的字段保存之。
  • 在新class中建立一个构造函数(constructor),接收源对象及原函数的所有参数作为参数。
  • 在新class中建立一个compute()函数。
  • 将原(旧)函数的代码拷贝到compute()函数中。如果需要调用源对象的任何函数,请以「源对象」值域调用。
  • 编译。
  • 在旧函数的函数体替换为上面新创建的类对象并调用compute()函数
  • 现在进行到很有趣的部分了。因为所有局部变量现在都成了字段,所以你可以任意分解这个大型函数,不必传递任何参数。

1.4.示例

这个实例的逻辑不需要关心,只需要观察它重构的过程。

 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;}

相关内容

热门资讯

今日重大通报“新道游有挂没有”... 您好:新道游这款游戏可以开挂,确实是有挂的,需要软件加微信【69174242】,很多玩家在新道游这款...
今日重大通报“微乐陕西三代到底... 您好:微乐陕西三代这款游戏可以开挂,确实是有挂的,需要软件加微信【6355786】,很多玩家在微乐陕...
玩家必看“手机微信麻将有没有挂... 您好:手机微信麻将这款游戏可以开挂,确实是有挂的,需要软件加微信【8700483】,很多玩家在手机微...
今日重大通报“方片十三张能不能... 您好:方片十三张这款游戏可以开挂,确实是有挂的,需要软件加微信【6355786】,很多玩家在方片十三...
「今日分享」 “友间十三张.究... 您好:友间十三张.这款游戏可以开挂,确实是有挂的,需要了解加客服微信【3636476】很多玩家在这款...