实现领域驱动设计----第五章

为什么使用实体

唯一的身份标识和可变性特征将实体对象和值对象区分开来。

有时,实体并不见得是一种适当的建模工具,而我们对实体的使用也有可能是不恰当的。很多时候,一个领域概念应该建模成值对象,而不是实体对象。

应用程序生成唯一标识
有很多可靠的方法都可以自动生成唯一标识,但是如果应用程序处于集群环境或者分布在不同的计算节点中,我们就需要额外小心了。有些方法可以生成完全唯一的标识,比如UUID(Universally Unique Identifier)或者GUID(Globally Unique Identifier)。以下是生成唯一标识的另一种方法,其中每一步生成的结果都将添加到最终的文本标识中:

  1. 计算节点的当前时间,以毫秒记
  2. 计算节点的IP地址
  3. 虚拟机(Java)中工厂对象实例的对象标识
  4. 虚拟机(Java)中由同一个随机数生成器生成的随机数

以下方式生成一个基于名字的UUID:

String rawId = java.util.UUID.nameUUIDFromBytes("Some text".getBytes()).toString();

另外,我们还可以对所生成的伪随机数进行加密:

SecureRandom randomGenerator = new SecureRandom();
int randomNumber = randomGenerator.nextInt();
String randomDigits = new Integer(randomNumber).toString();
MessageDigest encryptor = MessageDigest.getInstance("SHA-1");
byte[] rawIdBytes = encryptor.digest(randomDigits.getBytes());

里插入图片描述

将标识生成延迟到实体持久化时还有另外一个问题。当两个或多个实体需要加入到集合java.util.Set中时,由于此时它们都还没有实体标识,它们的默认标识值都是相等的(比如都为null,或者0,或者1)。如果实体的equals()方法比较的是实体标识,此时所有新建实体对象都被认为是同一个对象。所以只有第一个对象被保留下来,所有其他对象都被排除在集合之外。这将导致一个严重的bug,并且是一个难以查找的bug。

层超类型(Layer Super type)

public abstract class IdentifiedDomainObject implements Serializabel{
private long id = -1;
public IdentifiedDomainObject(){
super();
}
protected long id(){
return thid.id;
}

protected void setId(long anId){
this.id = anId;
}
}

这里的IdentifiedDomainObject便是层超类型,这是一个抽象基类,通过protected关键字,它向客户端隐藏了委派主键。所有实体都扩展自该抽象基类。早实体所处的模块之外,客户端根本就不用关心id这个委派标识。我们甚至可以将protected换为private。Hibernate既可以通过getter和setter方法来访问属性,也可以通过反射机制直接访问对象属性,故无论是使用protected还是private都是无关紧要的。另外,层超类型还有其他好处,比如支持乐观锁。

发现实体及其本质特征

限界上下文中的通用语言向我们提供了设计领域模型的概念术语。通用语言不是平白产生的,它必须通过与领域专家详细讨论之后才能得到。在通过语言的术语中,名词用于给概念命名,形容词用于描述这些概念,而动词则表示可以完成的操作。但是,如果我们认为对象就是一组命名的类和类上定义的操作,除此之外并不包含其他内容,那么,我们就错了。在领域模型中还可以包含很多其他内容。团队讨论和规范文档可以帮助我们创建更有意义的通用语言。

对象分裂症描述的是:委派对象根本不知道原来被委派对象的身份标识,因此我们无法知道委派对象那个的真正身份。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值