实体和值对象的聚合
标签:
架构设计
保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/27/ )。
在《面向对象中的实体和值对象》一文中,我们探讨了面向对象设计中的实体和值对象。本文将在前文的基础上继续探讨实体和值对象的分簇。
实体是对象,值对象也是对象。实体之间、实体和值对象之间互相引用,最终会形成一个图。如下所示。
实体之间,实体和值对象之间的互相引用是普遍的,因此这个图将是十分巨大的。这时面临一个拆分问题,即怎样将图拆分为多个块。
在UML中,存在聚合概念。聚合是指对象之间的部分和整体的关系,并且,部分可以脱离整体而单独存在。(如果部分无法脱离整体而单独存在,则为组合。)
在领域驱动设计(Domain-Driven Design,简称DDD)中,也存在聚合的概念。如果几个类必须强一致性地变化,则它们就属于一个聚合。例如,User、email、address等,它们都是和User一起变化的,因此属于一个聚合。这个聚合更像UML中的组合,因为email、address脱离了User后便失去了意义,因此具有和User相同的生命周期。
DDD中的聚合有以下特点:
- 存在一个聚合根,它是唯一可以被外界访问的对象,且一定是实体。例如,User就是聚合根,只有它可以被外界访问,email、address等属性都从属与它。即外部对象只能持有对聚合根的引用。
- 聚合内的各个对象都一致地变化,因此要被一起读写。为了实现这一点,往往将一个聚合组成一个表。也就是说,email,address信息都存在user表中。
- DDD的聚合中,非根的对象脱离了聚合根则没有意义。聚合根是核心,非根则是聚合根的说明与修饰。
因为外部只能引用聚合根,于是可以得到下面的图。
图中虚线内的部分为一个聚合,外部只能访问到聚合根,而不能直接访问其他节点。
聚合之间不需要强一致性地变动,可以放在不同的表中。
这样我们就可以实现聚合的划分,即系统的类的划分。
DDD中的聚合的概念是一种良好的类设计、类属性设计、类表结构设计的指导思想。
可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。