剑弑 发表于 2019-3-6 23:14:07

重构之搬移函数(Move Method)

      搬移函数(Move Method)???把类A的函数搬到类B?为什么要搬移呢?搬移了会更好看?更高大上么?{:2_33:}
      是的,搬移函数(Move Method)会让代码更高大上,会让代码更好理解也更好看。“搬移函数(Move Method)”是重构理论的重要支柱。当一个类具有太多行为,或一个类与另一个类有太多的合作而形成高度耦合,这时你就该看看自己的代码是不是该进行函数搬移了。因为通过这种重构手法,可以使我们系统中的类更简单,更干净利落的完成系统交付的任务,耦合度也会更低(只要你不是特意有意的提高耦合度);也能让我们对系统中的类具有更清晰的认识,优化起来更快捷。
   当我们遇到或写的函数使用另一个对象的次数比自己所驻对象更多时;一旦我们称动了类中的字段时;我们就要观察函数自己所驻类,调用类,以及继承体系中任何相关的,重定义函数。然后,根据函数与对象的交流次数的多少来决定称动路径。

class Account
    {
      private AccountType _type;
      private int _daysOverdrawn;

      public double overdraftCharge()
      {
            if (_type.isPremium())
            {
                double result = 10;
                if (_daysOverdrawn > 7)
                {
                  result += (_daysOverdrawn - 7) * 0.85;
                }
                return result;
            }
            else
            {
                return _daysOverdrawn * 1.75;
            }
      }

      public double bankCharge()
      {
            double result = 4.5;
            if (_daysOverdrawn > 0)
            {
                result += overdraftCharge();
            }
            return result;
      }
    }
class AccountType
    {
      public bool isPremium()
      {
            return true;
      }
上面我们有两个类,其中Account类中存在AccountType类的实例,过了几天我们在Account类增加了某些函数,又过了几天。。。。。又过了一段时间我们还要在Account类中增加行为,这样一直加导致Account类所承担的行为太多了;多到我们想找里面的一些函数都要很慢才能找出来,这时候我们就要观察是否有必要对Account类进行函数的搬移。
      刚好Account类中的overdraftCharge()函数它有调用到AccountType类中的isPremium()函数,哪么我们是否可以把overdraftCharge()搬移到AccountType类中呢?我们来试试看。首先我们先把overdraftCharge()函数整个复制到AccountType类中,然后把出现的Bug处理好;下面是搬移后的AccountType类。

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

      public bool isPremium()
      {
            return true;
      }
    }
因为原overdraftCharge()函数有使用到Account类中一个属性,但我们又没必要在AccountType类中增加一个属性,所以我们可以把它当成一个参数传入到函数中。函数搬移了,我们的Account类就可以变成这样了
class Account
    {
      private AccountType _type;
      private int _daysOverdrawn;

      public doube overdraftCharge()
      {
            return _type.overdraftCharge(_daysOverdrawn);
      }

      public double bankCharge()
      {
            double result = 4.5;
            if (_daysOverdrawn > 0)
            {
                result += _type.overdraftCharge(_daysOverdrawn);
            }
            return result;
      }
    }
有细心的朋友会看到Account类中的overdraftCharge()函数为什么没去掉呢?不去掉的话为什么要搬函数。。。。
是的,为什么不去掉呢?你可以选择去掉,但去掉之后必须要把原来对overdraftCharge()函数的调用改成对AccountType类overdraftCharge()函数的掉用。

注:如果某些特性只被你打算搬移的那个函数用到,你就应该一并把它搬移,如果有其他函数使用到了这个特性,你可以考虑将该特性的所有相关函数都一并搬移(有时候,搬移一组函数会比逐个搬移简单此)。

参考文献
重构——改善既有代码的设计   【美】Martin Fowler 著
                                                                         熊节 译



页: [1]
查看完整版本: 重构之搬移函数(Move Method)