剑弑 发表于 2019-3-4 23:01:38

重构之以函数对象取代函数(Replace Method With Method Object)

      当我们把一个业务的逻辑都写在一个函数里面的时候,函数会很长很长;而在函数里面临时变量是必不可少的,而且还可能会存在很多很多个临时变量。这时我们要想重构这个函数是非常困难且耗时的,而且重构出来后的结果也会不理想;因为函数长必然处理逻辑多,逻辑多就代表着要分解的函数多,分解的函数多代表着类承担的职责就多了,这是个很不好的行为(至于为什么以后会提到,现在我们暂时先不管这个)。      哪当我们要对这样的函数进行重构时,该怎么做呢?什么又叫做“以函数对象取代函数(Replace Method With Method Object)”的重构手法呢?我们先来看看一段代码

class Account
    {
      public int 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;
            return importantValue3 - 2 * importantValue1;
      }

      /// <summary>
      /// 这个是我偷懒写的一个函数
      /// </summary>
      /// <returns></returns>
      public int delta()
      {
            /*此处应是一系列逻辑运算*/
            return 1;
      }
}
    我们定义了一个类,类里面存在一个gamma()函数;从上面的代码我们可以看到gamma()函数既有参数传递进来,又存在了很多临时变量,临时变量里面的逻辑处理还要调用别的函数;gamma()函数处理的事情非常多,我们要进行提练函数(extract method)也并不好提取。
   我们该怎么做呢???我们该怎么做呢???我们该怎么做呢???
    首先,函数对象,函数对象嘛,必须要要一个类才能new一个对象啊!你都没有男(女)朋友怎么有对象呢?是吧!!!同样的你都不存在类怎么能new一个对象呢?所以我们第一步要做的就是先新建一个类,建立一个构造函数,把所有原函数的参数当做构造函数的参数。

class Gamma
    {
      private Account _account;
      private int inputVal;
      private int quantity;
      private int yearToDate;
      private int importantValue1;
      private int importantValue2;
      private int importantValue3;

      public Gamma(Account source,int inputValArg,int quantityArg,int yearToDateArg)
      {
            _account = source;
            inputVal = inputValArg;
            quantity = quantityArg;
            yearToDate = yearToDateArg;
      }
}

细心的你会发现,怎么会多传了一个Account类的实例呢?看下去你自然会明白。
新类建好了,接下来我们要做的事就是把Account类里面的原函数复制到新类Gamma里面,然后改正代码错误,相信这难不倒聪明的你;

public int compute()
      {
            importantValue1 = (inputVal * quantity) + _account.delta();
            importantValue2 = (inputVal*yearToDate) + 100;
            if ((yearToDate-importantValue1)>1000)
            {
                importantValue2 -= 20;
            }
            int importantValue3 = importantValue2 * 7;
            return importantValue3 - 2 * importantValue1;
      }
最后我们就可以对compute()函数进行提取,把Account类的原函数改成调用新类Gamma的compute()函数。重构后的代码如下

class Account
      {
            public int gamma(int inputVal, int quantity, int yearToDate)
            {
                return new Gamma(this, inputVal, quantity, yearToDate).compute();
            }

            /// <summary>
            /// 这个是我偷懒写的一个函数
            /// </summary>
            /// <returns></returns>
            public int delta()
            {
                /*此处应是一系列逻辑运算*/
                return 1;
            }
      }

      class Gamma
      {
            private Account _account;
            private int inputVal;
            private int quantity;
            private int yearToDate;
            private int importantValue1;
            private int importantValue2;
            private int importantValue3;

            public Gamma(Account source, int inputValArg, int quantityArg, int yearToDateArg)
            {
                _account = source;
                inputVal = inputValArg;
                quantity = quantityArg;
                yearToDate = yearToDateArg;
            }

            public int compute()
            {
                importantValue1 = (inputVal * quantity) + _account.delta();
                importantValue2 = (inputVal * yearToDate) + 100;
                importantThing();
                return importantValue2 * 7 - 2 * importantValue1;
            }

            public void importantThing()
            {
                if ((yearToDate - importantValue1) > 100)
                {
                  importantValue2 -= 20;
                }
            }
      }

相信看了重构后的代码你也应该知道为什么要传入一个Account类的实例了。


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



ibcadmin 发表于 2019-3-5 14:52:47

你这个重构系列的教程不错哟

剑弑 发表于 2019-3-5 17:49:38

ibcadmin 发表于 2019-3-5 14:52
你这个重构系列的教程不错哟

:lol:lol:lol:lol
页: [1]
查看完整版本: 重构之以函数对象取代函数(Replace Method With Method Object)