The DoYouHaoBaby PHP Framework中文开发文档手册
Copyright(c) DoYouHaoBaby.NET All Rights Reserved.
[ 值对象 ]

我们已经讨论了实体以及在建模阶段及早识别实体的重要性。实体在领域模型中是必需的对象。我们应该将所
有的对象视为实体吗?每一个对象都应该有一个标识符吗?

我们可能被引导将所有对象看成实体。实体是可以被跟踪的。但跟踪和创建标识符需要很大的成本。我们需要
保证每一个实体都有唯一标识,跟踪标识也并非易事。我们需要确保每个实例拥有它唯一的标识,跟踪标识也
并非易事。需要花费很多仔细的考虑来决定由什么来构成一个标识符,因为一个错误的决定可能会让对象拥有
相同的标识,而这并不是我们所预期的。

将所有的对象视为实体也会带来隐含的性能问题,因为需要对每个对象产生一个实例。如果Customer 是一个
实体对象,那么这个对象的一个实例标识一个特殊的银行客户,不能被对应其他客户的账户操作所复用,造成
的结果是必须为每一个客户建立一个这样的实例。这会导致系统在处理成千上万的实例时性能严重下降。

让我们考虑一个绘画应用。用户会看到一个画布且他能够用任何宽度、样式和颜色来画任何点和线。创建一个
叫做Point 的对象类非常有用,程序会对画布上的每一个点创建这个类的一个实例。这样的一个点会包含两个
属性对应屏幕或者画布的坐标。考虑每一个点都拥有标识符是必要的吗?它会有延续性吗?看上去与这样一个
对象相关的事情只有它的坐标。

这是我们需要包含一个领域对象的某些属性时的例子。我们对某个对象是什么不感兴趣,只关心它拥有的属性。
用来描述领域的特殊方面、且没有标识符的一个对象,叫做值对象。

区分实体对象和值对象非常必要。出于要统一的缘故而将所有对象处理成实体对象并没有太大帮助。实际上,只
建议选择那些符合实体定义的对象作为实体,将剩下的对象处理成值对象。这会简化设计,并且将会产生某些其
他的积极的意义。

没有标识符,值对象就可以被轻易地创建或者丢弃。没有人关心创建一个标识符,在没有其他对象引用时,垃圾
回收会处理这个对象。这极大简化了设计。

极力推荐值对象是不变的。它们由一个构造器创建,并且在它们的生命周期内永远不会被修改。当你希望一个对象
的不同的值时,你会简单地去创建另一个对象。这会对设计产生重要的结果。保持不变,并且不具有标识符,值对
象就可以被共享了。这对某些设计是必要的。不变的对象可在重要的性能语境中共享。它们也能表明一致性,如:
数据一致性。

  1. class test{   
  2.   
  3.    public $_valueObj1;   
  4.   
  5.    public $_valueObj2;   
  6.   
  7.    public function __consturct( $valueOjb1,$valueObj2 ){   
  8.       
  9.        $this->_valueObj1 = $_valueObj1;   
  10.        $this->_valueObj2 = $_valueObj2;   
  11.    }   
  12.     
  13. }  

一条箴言是:如果值对象是可共享的,那么它们应该是不可变的。值对象应该保持尽量的简单。当其他当事人
需要一个值对象时,可以简单地传递值,或者创建一个副本。制作一个值对象的副本是非常简单的,通常不会
有什么副作用。如果没有标识符,你可以按你所需创建若干副本,然后根据需要来销毁它们。



值对象可以包含其他的值对象,它们甚至还可以包含对实体对象的引用。虽然值对象可用来简化一个领域对象要
包含的属性,但这并不意味着它应该包含所有的一大长列的属性。属性可以被分组到不同的对象中。被选择用来
构成一个值对象的属性应该形成一个概念上的整体。一个客户会跟其名称、街道、城市、州县相关。最好分离出
一个对象来包含地址信息,客户对象会包含一个对地址对象的引用。街道、城市、州县应该归属于一个对象,因
为它们在概念上属于一体的,而不应该是作为分离的客户属性。

好了,本节到此结束。