关于值对象的应用

值对象一般应被设计为不可变的,这样就可以在任何对象中共享,由其是在分布式系统中,可以降低维护成本大幅提升系统性能。若值对象是可变的,就会影响所有引用它的对象。比如某种型号的铅笔是一个实体,而该型号铅笔的基本参数可以作为值对象被铅笔实体共享。若值对象是可变的,当改变任何一支铅笔的参数时,都会影响其它实体。OR/M 如何得知值对象已被加载?如何对值对象的生命周期进行监控?若值对象数量庞大时,这种监控是否会对系统性能造成麻烦?这种情况下相比非共享(拷贝)值对象哪种更有优势?请教了。

2010年03月04日 21:40 "hiswing"的内容
如何对值对象的生命周期进行监控

可能你对值对象含义没有真正把握,见这个讨论,值对象属于根实体管理的边界中,它的生命周期服从于实体。

2010年03月04日 21:40 "hiswing"的内容
若值对象是可变的,当改变任何一支铅笔的参数时,都会影响其它实体。

谈论值对象包括语义和语法两个层面。语义上的值对象是指缺乏标识,只有数据和行为的对象;语法上的值对象是指非引用类型对象(对象间赋值操作是值拷贝),与引用类型对象(对象间的赋值是引用拷贝)相对。

C++和C支持语法非引用类型对象;Java除了基本类型,都为引用类型对象。比如:Java中DateTime语义上为值对象,语法上却是引用类型。为弥补语法与语义的差异,Java中通常用不可变(final)修饰引用对象,强制需要改变的时候进行值拷贝(clone)。

但是,即使在Java中,还是int这样的基本类型作为真正的值类型。如果要思考值对象的生命周期,可以考察一下int这些基本类型的生命周期,在使用DateTime这类对象时应该尽量模拟int这些基本类型。


[该贴被weidagang2046于2010-03-05 10:03修改过]

可能我没说清楚,我知道值对象的生命周期取决于实体,这是值对象为不可变的设计。当值对象被设计为可变且是被共享的,此时若改变值对象中某个属性,将会影响所有引用它的实体对象。如何来解决这一问题?

2010年03月05日 18:58 "hiswing"的内容
此时若改变值对象中某个属性,将会影响所有引用它的实体对象。如何来解决这一问题?

我在上面那个帖子里说了,所有属性都是相当于加final,是不能改的,如果要改,就把整个值对象换了。重新建立一个值对象和当前实体建立关系。
这就是更换关联关系,不改变值对象的值。

2010年03月04日 21:40 "hiswing"的内容
值对象一般应被设计为不可变的,这样就可以在任何对象中共享

语义上的值是不可以被共享的,比如:我的一块钱和你的一块钱是相等的,但不能被共享。在Java语法上,你看看int型变量就知道,它根本不可能被共享。

2010年03月06日 15:41 "weidagang2046"的内容
语义上的值是不可以被共享的,比如:我的一块钱和你的一块钱是相等的,但不能被共享

呵呵,这就是值+对象和单纯int值的区别所在,值对象可以被共享,例如一个屋子里有100个插座,那么一栋房子有好几个房间,就有好几百个插座,这是很浪费的,对象世界中的flyweight模式就是来解决这个问题的。

2010年03月06日 21:20 "banq"的内容
对象世界中的flyweight模式就是来解决这个问题的

是的,flyweight是基于值语义的对象引用;被共享的对象语义上是值,语法上是引用。

不过,对于这个插座的例子,我认为不属于flyweight模式。这里的插座是更接近实体对象而非值,插座与房子的关系是聚合关系。

正如banq所说值对象是可以被共享的,其生命周期是服从于实体的,那么他生命周期该如何来监控呢?共享也就意味着vo可以被多个实体引用,而且还有可能被将来产生的实体引用,那么一定要确定该vo已经不被所有的实体引用,而且也不会被将来的实体引用,这样才能销毁这个值对象,但还能确认这两点,至少第二点非常难,那肯定会出现楼主所说的问题,也就是说值对象的生命周期会很长,而且可能会导致要持久化到数据库中,这样的话值对象不也就成了一个实体了吗,不知道我理解的对不对,请大牛们指教,谢谢

值对象共享导致生命周期延长可以通过常驻内存方式,比如数据网格 IMDG 等方式存在,数据库也可以了,但有并不意味就改变其性质了。