第2章 重新组织函数:函数对象替换算法

Posted 浅墨浓香

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第2章 重新组织函数:函数对象替换算法相关的知识,希望对你有一定的参考价值。

8. 以函数对象取代函数(Replace Method with Method Object)

8.1 动机

(1)将一个大型的函数放进一个单独对象中,使局部变量变成对象内的字段,然后可以在同一个对象中将这个大型函数分解为多个小型函数。

(2)局部变量的存在会增加函数分解的难度。如果局部变量太多,可以难以使用Replace Temp with Query来处理,这时可以用函数对象来取代

8.2 做法

(1)建立一个新类,根据待处理函数的用途,为这个类命名。

(2)在新类中建一个const字段,用以保存原先大函数所在的对象。我们将这个字段称为“源对象”。同时,针对原函数的每个临时变量和每个参数在新类中建立一个对应的字段保存之

(3)在新类中建立一个构造函数,接收源对象及原函数的所有参数作为参数。

(4)在新类中建立一个compute()函数。

(5)将原函数的代码复制到compute()函数中。如果需要调用源对象的任何函数,请通过源对象字段调用。

(6)将旧函数的函数本体替换为这样一条语句:“创建上述新类的一个新对象,而后调用其中的compute函数”。

8.3 范例

//以函数对象取代函数
//重构前
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;
        //and so on
        return importantvalue3 - 2 * importantValue1;
    }    
};

//重构后
//1.声明一个新类,提供一个const字段用以保存源对象;
//2.函数的每一个参数和每一个临时变量分别以一个字段保存
//3. 加入一个构造函数
class Gamma
{
private:
    const Account* _account;
    int inputVal;
    int quantity;
    int yearToDate;
    int importantValue1;
    int importantValue2;
    int importantValue3;
    
public:
    Gamma(Account* src,int inputVal, int quantity, int yearToDate):_account(src)
    {
        this->inputVal = inputVal;
        this->quantity = quantity;
        this->yearToDate = yearToDate;
    }
    
    int compute()
    {
        int importantValue1 = (inputVal * quantity) + _account->delta();//调用源对象的delta()
        int importantValue2 = (inputVal * yearToDate) + 100;
        if ((yearToDate - importantValue1) > 100)
            importantValue2 -= 20;
        
        int importantValue3 = importantValue2 * 7;
        //and so on
        return importantvalue3 - 2 * importantValue1;        
    } 
};

//修改Account类中的旧函数
int gamma(int inputVal, int quantity, int yearToDate)
{
    Gamma gm(this, inputVal, quantity, yearToDate);
    return gm.compute();
}

9. 替换算法(Substitute Algorithm)

9.1 动机

(1)将函数本体替换为另一个算法

(2)如果一件事可以有更清晰的方式来取代复杂的方式,则可以用此法重构。

(3)使用这项重构手法前,要先确定已经尽可能将函数分解为简单的小型函数,然后才能进行算法的替换工作。

9.2 做法

(1)准备好另一个(替换用的)算法,让它通过编译。

(2)针对现有测试,执行上述的新算法。如果结果与原本结果相同,重构结束

(3)如果测试结果不同于原先,在测试和调试过程中,以旧算法为比较参照标准。

9.3 范例

//替换算法(Java代码)
//重构前
String foundPerson(String[] people)
{
    for(int i = 0; i < people.length; i++)
    {
        if(people[i].equals("Don"))
            return "Don";
        
        if(people[i].equals("John"))     
            return "John";
        
        if(people[i].equals("Kent"))
            return "Kent";   
    }
}
//重构后
String foundPerson(String[] people)
{
    List candiates = Arrays.asList(new String[]{"Don","John","Kent"});
    for(int i = 0; i < people.length; i++)
    {
        if (candiates.contains(people[i]))
            return people[i];
    }
    
    return "";
}

以上是关于第2章 重新组织函数:函数对象替换算法的主要内容,如果未能解决你的问题,请参考以下文章

重构改善既有代码的设计--第6章--重新组织函数

第2章 重新组织函数:提炼函数

第2章 重新组织函数:引入解释性变量分解临时变量和移除对参数的赋值

第5章:函数式编程

第2章KNN算法笔记_函数classify0

20182311 2019-2020-1 《数据结构与面向对象程序设计》第7周学习总结