马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

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

  [复制链接]
查看2935 | 回复4 | 2019-3-4 23:01:38 | 显示全部楼层 |阅读模式
        当我们把一个业务的逻辑都写在一个函数里面的时候,函数会很长很长;而在函数里面临时变量是必不可少的,而且还可能会存在很多很多个临时变量。这时我们要想重构这个函数是非常困难且耗时的,而且重构出来后的结果也会不理想;因为函数长必然处理逻辑多,逻辑多就代表着要分解的函数多,分解的函数多代表着类承担的职责就多了,这是个很不好的行为(至于为什么以后会提到,现在我们暂时先不管这个)。      哪当我们要对这样的函数进行重构时,该怎么做呢?什么又叫做“以函数对象取代函数(Replace Method With Method Object)”的重构手法呢?我们先来看看一段代码
[C#] 纯文本查看 复制代码
 
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一个对象呢?所以我们第一步要做的就是先新建一个类,建立一个构造函数,把所有原函数的参数当做构造函数的参数。
[C#] 纯文本查看 复制代码
 
 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里面,然后改正代码错误,相信这难不倒聪明的你;
[C#] 纯文本查看 复制代码
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()函数。重构后的代码如下
[C#] 纯文本查看 复制代码
 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 | 显示全部楼层
你这个重构系列的教程不错哟
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
剑弑 | 2019-3-5 17:49:38 | 显示全部楼层
ibcadmin 发表于 2019-3-5 14:52
你这个重构系列的教程不错哟

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则