在C#中,我们经常说类型分为两种,值类型跟引用类型;同样的,我们也可对对象做这样的分类:引用对象和值对象。前者如“客户”、“帐户”等,每个对象都代表现实中的一个实物,我们可以直接拿来对比两个对象是否相等。后者如“日期”、“时间”、“钱”、等,这些完全是用数据值来定义,并不会在意副本的存在,一个系统中可以有成千上万的“日期”对象。 有时,我们要用一个类去存储一些不可修改的数据(这时它是一个值对象),但随着系统的壮大,我们会对这个类加入一些可修改数据,并确保对任何一个对象的修改都能影响到所有引用这对象的地方。这时候我们就需要对这个类进行“将值对象改为引用对象(Change Value to Reference)”重构,把值对象收为引用对象。
不知道大家还记不记得上一章写的“[url=重构之以对象取代数据值(Replace Data Value With Object) http://www.ibcibc.com/forum.php? ... 20&fromuid=9905 (出处: IBC编程社区-C#论坛-C#教程,ASP.NET教程-C#源码)]以对象取代数据值(Replace Data Value With Object)[/url]”,这一次我们从上一章重构后的代码为例子;
Customer类
[C#] 纯文本查看 复制代码 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 类
[C#] 纯文本查看 复制代码 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类使用(一个客户拥有多个不同的订单)。这就意味着我一个客户名称只有一个对象。所以首先我们要先提供一个统一入口,然后把构造函数改为私有函数:
[C#] 纯文本查看 复制代码 private Customer(string name)
{
Name = name;
}
public static Customer create(string name)
{
return new Customer(name);
}
我们有了统一的入口,但”客户“是会有多个的,所以我们要用一个集合数组(List、Dictionary等)来存储所有Customer 对象。
[C#] 纯文本查看 复制代码 private static Dictionary<string, Customer> _instancer;
private void store()
{
_instancer.Add(this.Name,this);
}
因为我们把对象都存到了_instancer里面,所以入口create函数就要改成
[C#] 纯文本查看 复制代码 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 对象呢,还是先预先创建。这个要看自己的业务需要,做出相应的调整;这里我们先用预先创建做例子。
[C#] 纯文本查看 复制代码 public static void loadCustomers()
{
new Customer("Lemon Car Hire").store();
new Customer("Associated Coffee Machines").store();
new Customer("Bilston Gasworks").store();
}
参考文献
重构——改善既有代码的设计 【美】Martin Fowler 著
熊节 译
|