实体、值对象、聚合


定义:

实体不仅需要知道它是什么,还要知道它是哪个,值对象只关心它是什么。

实体:许多对象不是由它们的属性来定义,而是通过一系列的连续性和标识来从根本定义的。只要一个对象在生命周期中能够保持连续性,并且独立于它的属性(即使这些属性对系统用户非常重要),那它就是一个实体。

值对象:当你只关心某个对象的属性时,该对象便可以作为一个值对象。为其添加有意义的属性,并赋予它相应的行为。我们需要将值对象看成不变对象,不要它任何身份标识,还应该尽量避免像实体对象一样的复杂性。

对于实体,实体核心是用唯一的标识符来定义,而不是通过属性定义。即使属性完全相同的也可能是不同的对象。同时实体本身是由状态的,实体有严谨的生命周期,实体本身会体现出相关的业务行为,业务行为会被实体属性或状态造成影响和改变。

值对象本身无状态,不可变,并且不分配具体的标识。本身无生命周期,也不会产生独立行为。

举个栗子:

1、手机由SN号识别,手机是一个实体。手机的配件这种场景下就是值对象。

2、体育场的座位,门票上有座位号,座位号可以最为唯一标识,座位是实体。但是如果门票没有座位号,先到先做,座位没有座位号,只有数量,坐一个少一个,这时候座位就是值对象。

值对象的使用目的:

使用不变的值对象使得我们做更少的职责假设。

值对象用于度量和描述事物,DDD中建议尽量使用值对象来建模而不是实体对象,因为值对象非常容易的进行创建、测试、使用、优化和维护。

值对象的特征:

1、它度量或者描述了领域的一件东西。

2、它可以作为不变量。

3、它可以将土拨杆的相关的属性结合成一个概念整体。

4、当度量和描述发生改变的时候,可以用另一个值对象替换。

5、它可以和其他值对象进行相等比较

6、它不会对协作对象造成副作用

最小化集成:

DDD项目中,通常存在多个限界上下文,这意味着我们需要找到合适的方法对这些上下文进行集成。当模型概念从上游上下文流入下游上下文时,尽量使用值对象表示这些概念。这样可以达到最小化集成,即可以最小化下游模型中用于管理职责的属性数数目。使用不便的值对象使得我们做更少的职责假设。

聚合与聚合根

定义了对象之间清晰的关系和边界,并实现领域模型的内聚。

必须将聚合作为一个修改数据的单元。

一个聚合必须有一个聚合根,根是聚合中的一个实体,通常聚合中其他实体需要依赖于聚合根,其他实体不能没有聚合根而存在,从业务的角度看它是没有单独存在的意义。

对一个聚合中的实体的访问和操作,必须通过这个聚合的聚合根开始,确保一致性规则。例如订单的总金额依赖每个订单项的总和。

一个聚合只有一个聚合根,聚合根是可以独立存在的,聚合中其他实体或者值对象依赖聚合根。

只有聚合根才能被外部访问到。

针对功能模块进行系统划分,粒度太粗,使用聚合可以精确划分粒度。