• 重构 改善既有代码的设计 Replace Method with Method Object(以函数对象取代函数)


    你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method

    将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。

    动机

    我们一直在强调,小型函数优美动人。只要将相对独立的代码从大型函数中提炼出来,就大大提高了函数的可读性。

    但是,局部变量的存在会增加函数分解难度。如果一个函数中局部变量泛滥成灾,那么这个时候Replace Temp with Query可以帮助你。有时候根本无法拆解一个需要拆解的函数,这时候Replace Method with Method Object就发挥作用了。

    Replace Method with Method Object会将所有局部变量都变成函数对象的字段。然后就可以对这个新函数使用Extract Method创造新函数,从而达到拆解的目的。

    范例

    如果要找到合适的例子,那么需要很长的篇幅,所以我们杜撰了这样一个函数。

    复制代码
    class Account
    {
          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;
               //and so on...
               return importantValue3 - 2 * importantValue1;
           }
           public int Delta()
           {
               return 100;
           }
    }
    复制代码

    为了把这个函数变成函数对象,首先声明一个新类。在新类中,提供一个字段用于保存原对象,同时也对函数的每个参数和每个临时变量,提供字段用于保存。

    复制代码
    class Gamma
    {
    
            private readonly Account _account;
    
            private readonly int _inputVal;
    
            private readonly int _quantity;
    
            private readonly int _yearToDate;
    
            private int _importantValue1;
    
            private int _importantValue2;
    
            private int _importantValue3;
    }
    复制代码

    接下来,加入一个构造函数:

    复制代码
    public Gamma(Account account, int inputVal, int quantity, int yearToDate)
    {
           _account = account;
           _inputVal = inputVal;
           _quantity = quantity;
           _yearToDate = yearToDate;
    }
    复制代码

    接下来,将原本的函数搬到Compute()中。

    复制代码
    public int Compute()
    {
        _importantValue1 = _inputVal * _quantity + _account.Delta();
        _importantValue2 = _inputVal * _yearToDate + 100;
        if (_yearToDate - _importantValue1 > 100)
        {
           _importantValue2 -= 20;
        }
        _importantValue3 = _importantValue2 * 7;
        //and so on...
        return _importantValue3 - 2 * _importantValue1;
    }
    复制代码

    完整的Gamma函数如下:

    复制代码
    class Gamma
    {
    
       private readonly Account _account;
    
       private readonly int _inputVal;
    
       private readonly int _quantity;
    
       private readonly int _yearToDate;
    
       private int _importantValue1;
    
       private int _importantValue2;
    
       private int _importantValue3;
    public Gamma(Account account, int inputVal, int quantity, int yearToDate) { _account = account; _inputVal = inputVal; _quantity = quantity; _yearToDate = yearToDate; } public int Compute() { _importantValue1 = _inputVal * _quantity + _account.Delta(); _importantValue2 = _inputVal * _yearToDate + 100; if (_yearToDate - _importantValue1 > 100) { _importantValue2 -= 20; } _importantValue3 = _importantValue2 * 7; //and so on... return _importantValue3 - 2 * _importantValue1; } }
    复制代码

    最后,修改旧函数,让它的工作委托给刚完成的这个函数对象。

    int Gamma(int inputVal, int quantity, int yearToDate)
    {
        return new Gamma(this, inputVal, quantity, yearToDate).Compute();
    }

    这就是本项重构的基本原则。它的好处是:现在我们可以轻松地对Compute()函数采取Extract Method,不必担心参数传递的问题。

    比如说我们对Compute进行如下重构:

    复制代码
    public int Compute()
    {
        _importantValue1 = _inputVal * _quantity + _account.Delta();
        _importantValue2 = _inputVal * _yearToDate + 100;
        GetImportantThing();
        _importantValue3 = _importantValue2 * 7;
        //and so on...
        return _importantValue3 - 2 * _importantValue1;
    }
    
    void GetImportantThing()
    {
        if (_yearToDate - _importantValue1 > 100)
        {
            _importantValue2 -= 20;
        }
    }
    复制代码
  • 相关阅读:
    RESTFul-service guideline
    logback推荐配置
    MongoDB 存活時間 TTL 用法
    IntelliJ IDEA 的热部署插件JRebel 安装及使用(破解)
    Idea远程调试
    学习方法记录
    2017年3月9日日记
    maven整合SSM总结
    【转】 SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
    【转】如何用Maven创建web项目(具体步骤)
  • 原文地址:https://www.cnblogs.com/gaoqiaoliangjie/p/10151072.html
Copyright © 2020-2023  润新知