剑弑 发表于 2019-3-25 23:38:19

重构之将值对象改为引用对象(Change Value to Reference)

       在C#中,我们经常说类型分为两种,值类型跟引用类型;同样的,我们也可对对象做这样的分类:引用对象和值对象。前者如“客户”、“帐户”等,每个对象都代表现实中的一个实物,我们可以直接拿来对比两个对象是否相等。后者如“日期”、“时间”、“钱”、等,这些完全是用数据值来定义,并不会在意副本的存在,一个系统中可以有成千上万的“日期”对象。       有时,我们要用一个类去存储一些不可修改的数据(这时它是一个值对象),但随着系统的壮大,我们会对这个类加入一些可修改数据,并确保对任何一个对象的修改都能影响到所有引用这对象的地方。这时候我们就需要对这个类进行“将值对象改为引用对象(Change Value to Reference)”重构,把值对象收为引用对象。
       不知道大家还记不记得上一章写的“http://www.ibcibc.com/forum.php?mod=viewthread&tid=8720&fromuid=9905 (出处: IBC编程社区-C#论坛-C#教程,ASP.NET教程-C#源码)]以对象取代数据值(Replace Data Value With Object)”,这一次我们从上一章重构后的代码为例子;
Customer类
public class Customer
{
    private string _name;
    /// <summary>
    /// 名称
    /// </summary>
    public string Name
    {
      get { return _name; }
      set { _name = value; }
    }

    private string _jName;
    /// <summary>
    /// 简称
    /// </summary>
    public string JName
    {
      get { return _jName; }
      set { _jName = value; }
    }

    private string _address;
    /// <summary>
    /// 地址
    /// </summary>
    public string Address
    {
      get { return _address; }
      set { _address = value; }
    }

}
Order 类
class Order
{
private string _customer;

public string Customers
{
get { return _customer; }
set { _customer = value; }
}

public Order(string customer)
{
CustomerClass =new Customer();
CustomerClass.Name = customer;
}
      public Order(string customer,string jname)
      {
            CustomerClass = new Customer();
            CustomerClass.Name = customer;
            CustomerClass.JName = jname;
      }

      public Order(Customer Customer)
      {
            CustomerClass = Customer;
      }
}
目前上面的代码都还是每一个Order类对象拥有各自的Customer类对象。但现在我希望改变这一情况,希望一个Customer类可以被多个Order类使用(一个客户拥有多个不同的订单)。这就意味着我一个客户名称只有一个对象。所以首先我们要先提供一个统一入口,然后把构造函数改为私有函数:
      private Customer(string name)
      {
            Name = name;
      }

      public static Customer create(string name)
      {
return new Customer(name);
      }
我们有了统一的入口,但”客户“是会有多个的,所以我们要用一个集合数组(List、Dictionary等)来存储所有Customer 对象。
private static Dictionary<string, Customer> _instancer;

      private void store()
      {
             _instancer.Add(this.Name,this);
      }
因为我们把对象都存到了_instancer里面,所以入口create函数就要改成
      public static Customer create(string name)
      {
            return getNamed(name);
      }

      public static Customer getNamed(string name)
      {
            return (Customer)_instancer.FirstOrDefault(a=>a.Key==name).Value;
      }

最后我们在决定应该在接到请求时创建新的Customer 对象呢,还是先预先创建。这个要看自己的业务需要,做出相应的调整;这里我们先用预先创建做例子。
public static void loadCustomers()
      {
            new Customer("Lemon Car Hire").store();
            new Customer("Associated Coffee Machines").store();
            new Customer("Bilston Gasworks").store();
      }



参考文献
重构——改善既有代码的设计   【美】Martin Fowler 著
                                                                         熊节 译





页: [1]
查看完整版本: 重构之将值对象改为引用对象(Change Value to Reference)