Move Method(搬移函数)

10.Move Method(搬移函数) - 图1

做法

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

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

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

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

  • 在目标类中声明这个函数

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

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

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

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

  • 编译目标类

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

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

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

  • 编译,测试

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

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

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

    你可以每修改一个引用点就编译并测试一次。也可以通过一次”查找/替换”改掉所有引用点,这通常简单一些

范例

  1. class Account...
  2. double overdraftCharge(){
  3. if (_type.isPremium()){
  4. double result = 10;
  5. if (_dayOverdrawn > 7) {
  6. result += (_dayOverdrawn -7) * 0.85;
  7. }
  8. return result;
  9. }
  10. else
  11. {
  12. return _dayOverdrawn * 1.75;
  13. }
  14. }
  15. double bankCharge(){
  16. double result = 4.5;
  17. if(_dayOverdrawn > 0){
  18. result += overdraftCharge();
  19. }
  20. return result;
  21. }
  22. private AccountType _type;
  23. private int _daysOverdrawn;
  24. }

修改后:

class Account...
  double overdraftCharge(){
      return _type.overdraftCharge(_daysOverdrawn);
    }

    double bankCharge(){
    double result = 4.5;
    if(_dayOverdrawn > 0){
      result += _type.overdraftCharge(_daysOverdrawn);
    }
    return result;
  }

    private AccountType _type;
    private int _daysOverdrawn;
}

class AccountType...
  double overdraftCharge(int dayOverdrawn){
      if (isPremium()){
      double result = 10;
      if (dayOverdrawn > 7) {
        result += (dayOverdrawn -7) * 0.85;
      }
      return result;
    }
      else
    {
      return dayOverdrawn * 1.75;
    }
    }
}