java move函数重新调用_Move Method (搬移函数)

Summary:

程序中,有个函数与其所驻类之外的另个一个函数进行更多的交流:调用后者,或者被后者调用。

在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是将旧函数完全移除。

Motivation:

“搬移函数”是重构理论的支柱。如果有一个类有太多行为,或如果一个类与另一个类有太多合作而形成高度耦合,就可以办以函数。通过这种手段,可以使系统中的类更简单,这些类最终也将更干净利落地实现系统交付的任务。

Mechanics:

1. 检查源类中被源函数所使用的一切特性(包括字段和函数),考虑它们是否也该被搬移。

如果某个特性只被打算搬移的那个函数用到,就应该将它一并搬移。如果另有其他函数使用了这个特性,可以考虑将使用该特性的所有函数全都一并搬移。有时候,搬移一组函数比逐一搬移简单些。

2.检查源类的子类和超类,看看是否有该函数的其他声明。

如果出现其他声明,或许无法进行搬移,除非目标类也同样表现出多态性。

3.在目标类中声明这个函数。

可以为此函数选择一个新名称—对目标类更有意义的名称

4. 将源函数的代码复制到目标函数中。调整后者,使其能在新类中正常运行

如果目标函数使用了源类中的特性,我们得决定如何从目标函数引用源对象。如果目标类中没有相应的引用机制,就得把源对象的引用当做参数,传给新建立的目标函数。

如果源函数包含异常处理,我们得判断逻辑上应该由哪个类来处理这一异常。如果应该由源类来负责,就把异常处理留在原地。

5. 编译目标类

6. 决定如何从源函数正确引用目标对象。

可能会有一个现成的字段或函数帮助取得目标对象。如果没有,就看能否轻松建立一个这样的函数。如果还是不行,就得在源类中新建一个字段来保存目标对象。这可能是一个永久性修改,但也可以让它是暂时的,因为后继的其他重构项目可能会把这个新建字段去掉。

7.修改源函数,使之成为一个纯委托函数

8.编译,测试

9. 决定是否删除源函数,或将它当作一个委托函数保留下来

如果要经常在源对象中引用目标函数,那么将源函数作为委托函数保留下来会比较简单。

10.如果要移除源函数,请将源类中对源函数的所有调用,替换为对目标函数的调用

11. 编译,测试。

范例

我们用一个表示账户的Account类来说明这项重构

public class Account

{

private AccountType type;

private int daysOverdrawn;

double overdraftCharge()

{

if( type.isPremium() )

{

double result = 10;

if( daysOverdrawn > 7 )

{

result += ( daysOverdrawn - 7 ) * 0.85;

return result;

}

}

else

{

return daysOverdrawn * 1.75;

}

return 0;

}

double bankCharge(){

double result = 4.5;

if( daysOverdrawn > 0 )

{

result += overdraftCharge();

}

return result;

}

} 假设有几种新账户,每一种都有自己的“透支金额计费规则”。所以我们希望将overdraftCharge() 搬移到AccountType 类去。

第一步要做的是:观察被overdraftCharge()使用的每一项特性,考虑是否值得将它们与overdraftCharge() 一起移动。此例中,我们需要让daysOverdrawn字段留在Account类,因为这个值不会随不同种类的账户而变化。然后,我们将overdraftCharge()函数复制到AccountType中,并做相应调整。

public class AccountType

{

double overdraftCharge( int daysOverdrawn )

{

if( isPremium() )

{

double result = 10;

if( daysOverdrawn > 7 )

{

result += ( daysOverdrawn - 7 ) * 0.85;

return result;

}

}

else

{

return daysOverdrawn * 1.75;

}

return 0;

}

} 调整目标函数使之通过编译,而后就可以将源函数的函数本体替换为一个简单的委托动作,然后编译测试。

public class Account

{

private AccountType type;

private int daysOverdrawn;

double overdraftCharge()

{

return type.overdraftCharge( daysOverdrawn );

}

...

} 我们可以保留代码现在的样子,也可以删除源函数。如果决定删除,就得找出源函数的所有调用者,并将这些调用重新定向,改为调用Account的overdraftCharge().

在所有的调用点都修改完毕后,就可以删除源函数在Account中的声明了。如果被搬移的函数不是private的,还要检查其他类是否是用了这个函数。

此例中被搬移的函数只引用了一个字段,所以只需要将这个字段作为参数传给目标函数就行了。如果被搬移的函数调用了Account中的另一个函数,就不能这么简单的处理。这种情况下必须将源对象传递给目标函数。

如果需要源类的多个特性,那么我们也可以将源对象传递给目标函数。不过如果目标函数需要太多源类特性,就得进一步重构。通常这种情况下,我们需要分解目标函数,并将其中一部分移回源类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值