重构对象-Move Method搬移函数一
创始人
2025-05-29 13:09:06

重构对象-Move Method搬移函数一

1.搬移函数

1.1.使用场景

当前类的函数与另外一个类有非常多的交流(调用关系),那么两个类之间有太多合作而形成高度耦合(highly coupled),我就会搬移函数。通过这种手段,我可以使系统中的classes更简单,这些classes最终也将更干净利落地实现系统交付的任务。

1.2.如何做

  • 浏览类中所有的属性和方法,寻找这样的函数:使用另一个对象的次数比使用自己所驻对象的次数还多,根据这个函数与哪个对象的交流比较多,决定其移动路径。
  • 如果某个属性只被你打算搬移的那个函数用到,你应该将它一并搬移。如果另有其他函数使用了这个特性,你可以考虑将使用该属性的所有函数全都一并搬移。有时候搬移一组函数比逐一搬移简单些。
  • 检查函数所在的原类、子类和父类,看看是否有该函数的其他声明。如果出现其他声明,你或许无法进行搬移,除非目标类也同样表现出多态性(polylmorphism〕。
  • 在目标类中声明这个函数。你可以为此函数选择一个新名称——对target class更有意义的名称。
  • 将source method的代码拷贝到target method中。调整后者,使其能在新类中正常运行。
  • 如果target method使用了原对象,你得决定如何从target method引用原对象。如果target class中没有相应的引用机制,就把source object reference当作参数,传给新建立的target class。
  • 如果source method包含异常处理式(exception handler),你得判断逻辑上应该由哪个来处理这一异常。如果应该由source class负责,就把异常处理式留在原地。
  • 编译target class。
  • 决定如何从source正确引用target object。
  • 可能会有一个现成的属性或函数帮助你取得target class。如果没有,就看能否轻松建立一个这样的函数。如果还是不行,你得在source class中新建一个新属性来保存target object。这可能是一个永久性修改,但你也可以让它保持暂时的地位,因为后继的其他重构项目可能会把这个新建属性去掉。
  • 修改source method,使之成为一个delegating method(纯委托函数也叫代理函数)。
  • 编译,测试。
  • 决定「删除source method」或将它当作一个delegating method保留下来。
  • 如果你经常要在source object中引用target method,那么将source method作为delegating method保留下来会比较简单。
  • 如果你想移除source method,请将source class中对source method的所有引用动作,替换为「对target method的引用动作」
  • 编译,测试。

1.3.示例

我用一个表示「帐户」的account class来说明这项重构

class Account...//译注:透支金计费,它和其他class的关系似乎比较密切。double overdraftCharge() {// 传入不同类型的账户if (_type.isPremium()) {double result = 10;if (_daysOverdrawn > 7) result += (_daysOverdrawn - 7) * 0.85;return result;}else return _daysOverdrawn * 1.75;}double bankCharge() {double result = 4.5;if (_daysOverdrawn > 0) result += overdraftCharge();return result;}private AccountType _type;private int _daysOverdrawn;

假设有多种类型的帐户,每一种都有自己的「透支金计费规则」。所以我希望将overdraftCharge()搬移到AccountType class去。

第一步要做的是:
1.观察被overdraftCharge()使用的每一特性(特性也叫属性),考虑是否值得将它们与overdraftCharge()—起移动。此例中我需要让daysOverdrawn属性留在Account class,因为其值会随不同种类的帐户而变化。
2.然后,我将overdraftCharge()函数码拷贝到AccountType中,并做相应调整。

class AccountType...// 函数拷贝到AccountType类// 添加参数,接收 daysOverdrawndouble overdraftCharge(int daysOverdrawn) {// 账户类型去掉对象调用,直接使用isPremium()if (isPremium()) {double result = 10;if (daysOverdrawn > 7) result += (daysOverdrawn - 7) * 0.85;return result;}else return daysOverdrawn * 1.75;}

在这个例子中,调整内容如下:
1.对于「使用AccountType特性」的语句,去掉_type对象引用;
2.想办法得到原类的属性或对象,我有四种选择:
(1)将这个属性也移到target class;
(2)建立或使用一个从target class到source的引用〔指涉)关系;
(3)将source object当作参数传给target class;
(4)如果所需特性是个变量,将它当作参数传给target method。

本例中我将_daysOverdrawn变量作为参数传给target method,使用了上述的第四个方式。

调整target method使之通过编译,而后我就可以将source method的函数本体替换为一个简单的委托动作(delegation),然后编译并测试:

class Account...double overdraftCharge() {// 在原类中调用目标类的方法	return _type.overdraftCharge(_daysOverdrawn);}

我可以保留代码如今的样子,也可以删除source method。如果决定删除,就得找出source method的所有调用者,并将这些调用重新定向,改调用Account的bankCharge():

class Account...// 删除了原函数 overdraftCharge()double bankCharge() {double result = 4.5;// 原函数引用点都改为调用新函数if (_daysOverdrawn > 0) result += _type.overdraftCharge(_daysOverdrawn);return result;}

所有调用点都修改完毕后,我就可以删除source method在Account中的声明了。我可以在每次删除之后编译并测试,也可以一次性批量完成。如果被搬移的函数不是private,我还需要检查其他classes是否使用了这个函数。在强型(strongly typed) 语言中,删除source method声明式后,编译器会帮我发现任何遗漏。

此例之中被移函数只取用(指涉〕一个值域,所以我只需将这个值域作为参数传给target method就行了。如果被移函数调用了Account中的另一个函数,我就不能这么简单地处理。这种情况下我必须将source object传递给target method:

class AccountType...// overdraftCharge()调用了Account类中的getDaysOverdrawn()方法,因此必须接收Account对象double overdraftCharge(Account account) {if (isPremium()) {double result = 10;if (account.getDaysOverdrawn() > 7)result += (account.getDaysOverdrawn() - 7) * 0.85;return result;}else return account.getDaysOverdrawn() * 1.75;}

如果我需要source class的多个特性,那么我也会将source object传递给target method。不过如果target method需要太多source class特性,就得进一步重构。通常这种情况下我会分解target method,并将其中一部分移回source class。

相关内容

热门资讯

L... ◆概述病毒和恶意软件日益成为计算机系统的最大威胁。 近年来,随着Linux系统在云计算和企业服务中的...
火... 目录1、软件介绍2.下载地址软件介绍Tinder 安全软件在用户中拥有非常好的声誉。 它完全免费,没...
中建八局又成立新公司了 (来源:建筑业那点事儿)前两天,上海港灏房地产有限公司正式成立了。我也去查了查这公司的底细,法定代表...
一地生娃奖房子 转自:扬子晚报“生育二孩购房奖补25平方米,生育三孩奖补50平方米”。近日,有网友晒出一张“竹山县生...
专家:海南自贸港开放政策红利已... 中新网三亚12月27日电 (张月和)“海南自贸港的开放政策红利已经逐步释放。”中国服务贸易协会副会长...