重新组织数据之三 :Change Value to Reference(将实值对象改为引用对象)
来源:互联网 发布:淘宝神笔怎么关联 编辑:程序博客网 时间:2024/06/05 02:39
你有一个class,衍生出许多相等实体(equal instances),你希望将它们替换为单一对象。
将这个value object (实值对象)变成一个reference object (引用对象)。
动机(Motivation)
在许多系统中,你都可以对对象做一个有用的分类:reference object和value objects。前者就像「客户」、「帐户」这样的东西,每个对象都代表真实世界中的一个实物,你可以直接以相等操作符(==,用来检验同一性,identity)检査两个对象 是否相等。后者则是像「日期」、「钱」这样的东西,它们完全由其所含的数据值来定义,你并不在意副本的存在;系统中或许存在成百上千个内容为"1/1/2000"的「日期」对象。当然,你也需要知道两个value objects是否相等,所以你需要覆写equals()和hashCode())。
要在reference object和value objects之间做选择有时并不容易。有时候,你会从一个简单的value objects开始,在其中保存少量不可修改的数据。而后,你可能会希望给这个对象加入一些可修改数据,并确保对任何一个对象的修改都能影响到所有引用此一对象的地方。这时候你就需要将这个对象变成一个reference object。
作法(Mechanics)
5译注:此处之factory method不等同于GoF在《Design Patterns》书中提出的Factory Method。为避免混淆,读者应该将此处的factory method理解为"Creational Method",亦即「用以创建某种实体」的函数,这个概念包含GoF的Factory Method,而又比Factory Method广泛。
范例(Example)
在Replace Data Value with Object 一节中,我留下了一个重构后的程序,本节范例就从它开始。我们有下列的Customer class:
class Customer {
public Customer (String name) {
_name = name;
}
public String getName() {
return _name;
}
private final String _name;
}
它被以下的Ordre class使用:
class Order...
public Order (String customerName) {
_customer = new Customer(customerName);
}
public void setCustomer(String customerName) {
_customer = new Customer(customerName);
}
public String getCustomerName() {
return _customer.getName();
}
private Customer _customer;
此外,还有一些代码也会使用Customer对象:
private static int numberOfOrdersFor(Collection orders, String customer) {
int result = 0;
Iterator iter = orders.iterator();
while (iter.hasNext()) {
Order each = (Order) iter.next();
if (each.getCustomerName().equals(customer)) result++;
}
return result;
}
到目前为止,Customer对象还是value object。就算多份定单属于同一客户,但每个Order对象还是拥有各自的Customer对象。我希望改变这一现状,使得一旦同 一客户拥有多份不同定单,代表这些定单的所有Order对象就可以共享同一个Customer对象。本例中这就意味:每一个客户名称只该对应一个Customer对象。
首先我使用 Replace Constructor with Factory Method。这样,我就可以控制Customer对象的创建过程,这在以后会是非常重要的。我在Customer class中定义这个factory method:
class Customer {
public static Customer create (String name) {
return new Customer(name);
}
然后我把「对构造函数的调用」替换成「对factory method的调用」:
class Order {
public Order (String customer) {
_customer = Customer.create(customer);
}
然后我再把构造函数声明为private:
class Customer {
private Customer (String name) {
_name = name;
}
现在,我必须决定如何访问Customer对象。我比较喜欢通过另一个对象(例如Order class中的一个值域)来访问它。但是本例并没有这样一个明显的值域可用于访问Customer对象。在这种情况下,我通过会创建一个注册(登录)对象,作为访问点。为了简化我们的例子,我把Customer对象保存在Customer class的一个static值域中,让Customer class作为访问点:
private static Dictionary _instances = new Hashtable();
然后我得决定:应该在接到请求时创建新的Customer对象,还是应该预先将它们创建好。这里我选择后者。在应用程序的启动代码(start-up code)中,我先把需要使用的Customer对象加载妥当。这些对象可能来自数据库,也可能来自文件。为求简单起见,我在代码中明确生成这些对象。反正以后我总是可以使用 Substitute Algorithm 来改变它们的创建方式。
class Customer...
static void loadCustomers() {
new Customer ("Lemon Car Hire").store();
new Customer ("Associated Coffee Machines").store();
new Customer ("Bilston Gasworks").store();
}
private void store() {
_instances.put(this.getName(), this);
}
现在,我要修改factory method,让它返回预先创建好的Customer对象:
public static Customer create (String name) {
return (Customer) _instances.get(name);
}
由于create()总是返回既有的Customer对象,所以我应该使用Rename Method 修改这个factory method的名称,以便强调(说明)这一点。
class Customer...
public static Customer getNamed (String name) {
return (Customer) _instances.get(name);
}
- 重新组织数据之三 :Change Value to Reference(将实值对象改为引用对象)
- 重新组织数据之四 :Change Reference to Value(将引用对象改为实值对象)
- Change Value to Reference(将实值对象改为引用对象)
- 重新组织数据之七 :Change Unidirectional Association to Bidirectional(将单向关联改为双向)
- 重新组织数据之八 :Change Bidirectional Association to Unidirectional(将双向关联改为单向)
- Change Reference to Value(将引用对象改变为实值对象)
- 重新组织数据之二 :Replace Data Value with Object(以对象取代数据值)
- 重新组织数据(三)
- 重新组织数据之五 :Replace Array with Object(以对象取代数组)
- 重构系列之对象属性的重构:《重构》重新组织数据
- 将对象改为引用对象 值对象和引用对象
- 将值对象改为引用对象
- 重新认识java(三) ---- 面向对象之继承!
- 重新认识java(三) ---- 面向对象之继承!
- 对象引用(object reference)与对象指针的区别
- 函数参数之 传常引用(passed by reference to const)替换 传值(passed by value)
- 函数参数之 传常引用(passed by reference to const)替换 传值(passed by value)
- 重新组织数据(一)
- java----Java面向对象
- [Django1.5]TemplateSyntaxError: 'comments' is not a valid tag library错误
- 多线程断点续传文件下载原理
- Merge change requests
- completion
- 重新组织数据之三 :Change Value to Reference(将实值对象改为引用对象)
- SAP表格维护生成器生成数据表维护视图程序
- android 中ActivityUI装态保存
- 图片转PDF的实现方法
- how to see sap notes
- 字符集(Charset)和字符编码(Encoding)
- HTTP协议详解
- Android4.0.3修改启动动画和开机声音
- Shutdown Normal or Shutdown Immediate Hangs. SMON disabling TX Recovery