当一个对象用于对事务进行描述而没有唯一标识时,它被称作值对象(Value Object)。
值对象通常是用来度量和描述事物。我们可以非常容易的对其进行创建,测试,使用,优化和维护,所以在建模时,我们尽量采用值对象来建模。
@Data
public class ColorInfo{
private String name;
private String css;
private String width;
}
{
"name":"yellow",
"css":"#FFFF00",
"width":"100px"
}
常见的值对象有数字、文本字符串、日期时间、人的全名、货币、颜色、地址等等。
当你考虑一个对象是否能够作为值对象时,你需要考量它是否有一下特征:
- 它度量或者描述了领域中的一件东西
- 它可以作为不变量
- 例如String类,它的所有改变自身属性的方法都是返回一个新的String对象实现。
- 它将不同的相关的属性组合成了一个概念整体
- 当度量和描述改变时,可以用另外一个值对象予以替换
- 它可以与其他值对象进行相等性比较
- 它不会对协作对象造成副作用
- 因为值对象是不可变的,所以不存在对对象产生修改的副作用(简单的说不会有set方法的输入)
如果想修改值对象时改如何处理?
public class ColorInfoManager {
@Getter
private ColorInfo yellow;
@Getter
private ColorInfo dark;
private void setYellow(ColorInfo yellow) {
this.yellow = yellow;
}
private void setDark(ColorInfo dark) {
this.dark = dark;
}
public ColorInfoManager() {
}
public ColorInfoManager(ColorInfo yellow, ColorInfo dark) {
this.setYellow(yellow);
this.setDark(dark);
}
public ColorInfoManager(ColorInfo yellow) {
this.setYellow(yellow);
}
public ColorInfoManager addYellowColorInfo(ColorInfo colorInfo) {
return new ColorInfoManager(colorInfo);
}
public ColorInfoManager addDarkColorInfo(ColorInfo colorInfo) {
return new ColorInfoManager(yellow, colorInfo);
}
}
如上诉代码,当需要修改值对象的某个属性的时候在方法中重新构造一个新的对象返回,这样可以保证值对象的不变性。
类型 | 是否需要唯一标记 | 是否可变 | 是否能持有实体引用(不同聚合根) | 是否可替换 |
---|---|---|---|---|
实体 | 是 | 是 | 否 | 否 |
值对象 | 否 | 否 | 否 | 是 |
- 业务建模的时候什么东西建成实体,什么东西建成值对象?
如何一个模型是需要有生命周期(有持久化和后续重建修改) 的需求那么应该建模成实体,否则应该建模成值对象
比如:一个商品的下单时间、下单人,你是无法修改的,