Replace Data Value with Object (以对象取代数据值)

Summary:  

有一个数据项,须要与其余数据和行为一块儿使用才有意义。将数据项变成对象。 java

Motivation: 

开发初期,咱们以简单的数据项表示简单的状况。可是随着开发的进行,你可能会发现,这些简单数据项再也不那么简单了。好比说,一开始你可能会用一个字符串来表示“电话号码”概念,可是随后就会发现,电话号码须要“格式化”、“抽取区号”之类的特殊行为。若是这样的数据有一两个,还能够把相关函数放进数据项所属的对象里;可是Duplicate Code坏味道和Feature Envy坏味道很快就会从代码中散发出来。当这些坏味道开始出现,就应该将数据值变成对象。 函数

Mechanics: 

1.为带替换数据新建一个类,在其中声明一个final字段,其类型和源类中的带替换数值类型同样。而后在新类中加入这个字段的取值函数,再加上一个接受此字段为参数的构造函数。 测试

2.编译 this

3. 将源类中的带替换数值字段的类型改成前面新建的类。 spa

4. 修改源类中该字段的取值函数,令它调用新类的取值函数。 code

5. 若是源类构造函数中用到这个待替换字段,咱们就修改构造函数,令它改用新类的构造函数来对字段进行赋值动做。 对象

6.修改源类中待替换字段的设值函数,令它为新类建立一个实例。 开发

7.编译,测试 字符串

8. 如今,可能须要对新类使用Change Value to Reference. get

范例

下面有一个表明“订单”的Order类,其中以一个字符串记录订单客户。如今,咱们但愿改用一个对象来表示客户信息,这样就有充裕的弹性保存客户地址、信用等级等信息,也得以安置这些信息的操做行为。Order类最初以下:

public class Order
{
    private String customer;

    public Order( String customer )
    {
        this.customer = customer;
    }

    public String getCustomer()
    {
        return customer;
    }

    public void setCustomer( String arg )
    {
        customer = arg;
    }
}

使用Order类的代码可能像下面这样:

private static int numberOfOrdersFor( Collection orders, String customer )
{
   int result = 0;
   Iterator<Order> iter = orders.iterator();
    while( iter.hasNext() )
    {
        Order each = iter.next();
        if( each.getCustomer().equals( customer ) )
        {
            result++;
         }
     }
    return result;
}

首先,新建一个Customer类表示“客户”概念。而后在这个类中创建一个final字段,用以保存一个字符串,这是Order类目前所使用的。将这个新字段命名为name,为这个字符串加上取值函数和构造函数.

public class Customer
{
    private final String name;

    public Customer( String name )
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }
}
如今,将Order中的customer字段的类型修改成Customer,并修改全部引用该字段的函数,让它们恰当地改而引用Customer对象。其中取值函数和构造函数的修改都很简单。至于设值函数,让它建立一个customer实例。

public class Order
{
    private Customer customer;

    public Order( String customer )
    {
        this.customer = new Customer( customer );
    }

    public String getCustomer()
    {
        return customer.getName();
    }

    public void setCustomer( String arg )
    {
        customer = new Customer( arg );
    }
}
设值函数须要建立一个Customer实例,这是由于之前的字符串是个值对象,因此如今的Customer对象也应该是个值对象。这也就意味着每一个对象都包含本身的一个Customer对象。注意这样一条规则:值对象应该是不可修改内容的--这即可避免一些讨厌的别名问题。

咱们须要观察Order类中的customer字段的操做函数,并做出一些修改,使它更好地反映出修改后的新形势。对于取值函数,可使用Rename Method改变名称,让它更清晰地表示,它所返回的是消费者名称,而不是个Customer对象。

public void setCustomerName( String arg )
{
   customer = new Customer( arg );
}
至于构造函数和设值函数,就没必要修改其签名了,但参数名称得改:

public Order( String customerName )
{
   customer = new Customer( customerName );
}
public void setCustomerName( String customerName )
{
   customer = new Customer( customerName );
}
后继的其余重构也许会添加“接受现有Customer对象做为参数”的构造函数和设值函数。
相关文章
相关标签/搜索