关于实体与值对象的问题

在我理解,一个领域对象是实体对象还是值对象,主要是根据应用场景来决定的。

那假如说在一个系统中,有一个领域对象在某一个应用场景中属于值对象的范畴,但是在另一个场景中却属于实体对象,那么这个对象应该如何设计?

用现实生活中的例子来说明吧:

我们平时买东西都是用人民币来支付,这个时候,不管是一张一百块的,还是2张五十的或者是十张十块的,它们是等值的,我认为这个时候就相当于系统中的值对象。但是我们知道,每张人民币又都是不一样的,因为每张人民币都有自己唯一的编号还有印刷年份,生活中就有人喜欢收集一些特殊编号的人民币,这个时候的人民币就不能用值对象的方式来表示,只能以实体的方式出现。

那么请问,系统中如果出现这样的需求,那应该如何设计像人民币这类的对象。

我们借鉴dddexample里面的例子。

首先设计两个接口:

public interface Entity<T> {

public boolean samePrimaryKeyAs(T other);
}

public interface ValueObject<T> {

public boolean sameValueAs(T other);

}

那像这类的领域对象是要实现这两个接口呢?还是只实现Entity接口,然后在充当值对象的时候调用equals方法?

值对象中除了“值”不需要标示别的内容,如果需要加入业务过程就成为实体了。

首先需要确认的是同一个类型的东西在不同的地方需要的形式不同,人民币在支付体系中是“值”就足够了,如果在收藏界那才可能需要加入其他的业务过程成为实体了。首先要确认应用场景

>首先需要确认的是同一个类型的东西在不同的地方需要的形式不同,人民币在支付体系中是“值”就足够了,如果在收藏界那才可能需要加入其他的业务过程成为实体了。首先要确认应用场景

那我是不是可以这样进行设计:

/**
* 人民币的流水号,唯一标识
*/
public class RenMinBiSN implements ValueObject<RenMinBiSN> {

private String value;

public RenMinBiSN(String value) {
this.value = value;
}

public boolean sameValueAs(RenMinBiSN other) {
return value.equals(other.value);
}

public String toString() {
return value;
}

}

/**
* 人民币,实现了实体接口与值对象接口。
*/
public class RenMinBi implements Entity<RenMinBi>,ValueObject<RenMinBi> {

private RenMinBiSN renMinBiSN;

private final Integer value;

public RenMinBi(Integer value) {
this.value = value;
}

public RenMinBiSN getRenMinBiSN() {
return renMinBiSN;
}

public void setRenMinBiSN(RenMinBiSN renMinBiSN) {
this.renMinBiSN = renMinBiSN;
}

public Integer getValue() {
return value;
}

public boolean samePrimaryKeyAs(RenMinBi other) {
return this.renMinBiSN.equals(other.getRenMinBiSN());
}

public boolean sameValueAs(RenMinBi other) {
return this.value.equals(other.getValue());
}

}

[该贴被snow0613于2009-05-04 23:41修改过]
[该贴被snow0613于2009-05-04 23:42修改过]

你的问题还是在于没有确认这个对象需要面对的使用场景。
你是想用它支付么?那么不需要sn。
你是想用它收藏么?那么SN可能没有必要单独封装,这样会比较繁琐。SN,币值直接放到一个对象里就可以了。

咕~~(╯﹏╰)b

看来我还是没把问题表述清楚啊!

关于SN,我只是想用它来说明人民币这个类的每个对象有唯一标识,当然也可以直放到一个对象里,在这里我只是想起一种强调作用罢了,意义不大!

另外,我不是很明白你的意思。我还是重新把我的困扰说一遍吧。简单地说,就是支付体系与收藏体系在同一个系统,只是功能不一样的子模块罢了,而这个对象可能在这两个模块中进行穿插、切换。

换句话说,就是某个领域对象在大部分的时间内属于值对象(支付体系),只有在特定场景中属于实体对象(收藏体系)。

=====================================================
其实在人民币这个应用中,个人以为它首先是一个实体对象,然后才是一个值对象。(虽然被当做值对象使用的时候较多)。

个人认为,只要是可以创造出来(或者说可扩展)的领域对象,从本质上说应该都属于实体对象,因为它们都具有唯一特性,只是还属于某个类的范畴。就像是人民币,因为它也是被创造出来的东西。还有像客户类型之类的,因为是可扩展的。

而值对象,我觉得从根本上讲,应该是跟实体对立的,或者可以说抽象的,而且有一个固定的范畴。

哦,我终于基本上明白你的意思了~~
你想描述一个完整的RMB,他可能被应用在不同的场景下。这样你应该优先考虑实体的设计,值仅仅是他众多业务功能中的一个,而且也不是特殊的类型,不应该特殊考虑更没有从属关系。

显然对于当代货币来讲:币值、标识、防伪===信息都是必不可少的属性,将他们分开考虑必然是不恰当的。

在我的经验中“值对象”是很少用到的,单单为传递一个或者一组值建立对象往往意义不大。“值对象”在很多人的观念中被过分扩大了,这可能源于“贫血”的思想,我个人觉得不恰当。我对“贫血”的观点你可以查查我的文档。

我觉得作为这个领域的货币设计者是领域专家,我们想象他是怎么设计这个货币的?就不难发现了,我觉得每张货币虽然有编号和具体标识,但货币总归就有固定的面值,每个面值底下的货币就有一个编号是实体..不知道我分析的对不对?