Move Field (搬移字段)

Summary:  

程序中,某个字段被其所驻类之外的另一个类更多地用到。在目标类新建一个字段,修改源字段的所有用户,令它们改用新字段。

Motivation: 

 在类之间移动状态和行为,是重构过程中必不可少的措施。随着系统的发展,你会发现自己需要新的类,并需要将现有工作责任拖到新类中。

对于一个字段,在其所驻类之外的另一个类中有更多函数使用了它,我们就可以考虑搬移这个字段。上述所谓“使用”可能是通过设值/取值函数间接进行的。我们也可能移动该字段的用户(某个函数),这取决于是否需要保持接口不受变化。如果函数看上去更适合待在原地,那么就搬移字段。

Mechanics: 

1. 如果字段的访问级是public,使用 Encapsulate Field将它封装起来。

如果有可能移动移动那些频繁访问该字段的函数,或如果有许多函数访问某个字段,先使用SelfEncapsulate Field也许会有帮助。

2.编译,测试

3.在目标类中建立与源字段相同的字段,并同时建立相应的设值/取值函数。

4. 编译目标类。

5. 决定如何在源对象中引用目标对象。

可能会有一个现成的字段或函数帮助取得目标对象。如果没有,就看能否轻松建立一个这样的函数。如果还是不行,就得在源类中新建一个字段来保存目标对象。这可能是一个永久性修改,但也可以让它是暂时的,因为后继的其他重构项目可能会把这个新建字段去掉。

6. 删除源字段。

7.将所有对元字段的引用替换为对某个目标函数的调用。

如果需要读取该变量,就把对源字段的引用替换为对目标取值函数的调用;如果要对该变量赋值,就把对源字段的引用替换成对设值函数的调用。

如果源字段不是private的,就必须在源类的所有子类中查找源字段的引用点,并进行相应替换。

           8. 编译,测试。

范例1

下面是Account类的部分代码


public class Account
{
    private AccountType type;

    private double interestRate;

    double interestForAmountDays( double amount, int days )
    {
        return interestRate * amount * days / 365;
    }
}
我们把表示利率的interestRate搬移到AccountType类去。目前已有数个函数引用了它,interestForAmountDays() 就是其一。下一步我们要在AccountType中建立interestRate字段以及相应的访问函数:



public class AccountType
{
    private double interestRate;

    public double getInterestRate()
    {
        return interestRate;
    }

    public void setInterestRate( double interestRate )
    {
        this.interestRate = interestRate;
    }
}
这时候,可以编译新的AccountType类了。


现在我们需要让Account类中访问interestRate字段的函数转而是用AccountType对象,然后删除Account类中的interestRate字段。我们必须删除源字段,才能保证其访问函数的确改变了操作对象,编译器会帮我们指出未被正确修改的函数。


public class Account
{
    private AccountType type;

    double interestForAmountDays( double amount, int days )
    {
        return type.getInterestRate() * amount * days / 365;
    }
}

范例2:使用Sel-Encapsulation

如果有很多函数已经使用了interestRate字段,我应该先运用Self-Encapsulate Field(自我封装)


public class Account
{
    private AccountType type;

    private double interestRate;

    double interestForAmountDays( double amount, int days )
    {
        return getInterestRate() * amount * days / 365;
    }

    private void setInterestRate( double arg )
    {
        interestRate = arg;
    }

    private double getInterestRate()
    {
        return interestRate;
    }
}
这样,在字段搬移之后,我就只需要修改访问函数;



public class Account
{
    private AccountType type;

    double interestForAmountDays( double amount, int days )
    {
        return getInterestRate() * amount * days / 365;
    }

    private void setInterestRate( double arg )
    {
        type.setInterestRate( arg );
    }

    private double getInterestRate()
    {
        return type.getInterestRate();
    }
}


以后若有必要,我们可以修改访问函数的用户,让它们使用新对象。Self-Encapsulate Field是的我们得以保持小步前进。如果我需要对类做许多处理,保持小步前进时有帮助的。特别值得一提的是:首先使用Self-Encapsulate Field是我们得以更轻松使用Move Method将函数搬移到目标类中。如果待搬移函数引用了字段的访问函数,那些引用点是无需修改的。


你可能感兴趣的:(Move Field (搬移字段))