模型的构造块:实体、值对象、领域服务
-
(1)实体的领域特征
-
在领域中,一个由身份而不是属性值定义的客观概念就是实体,这个身份可以由一个唯一标识确认。
一个概念是否是实体取决于系统的应用场景,一个标识是否能保证唯一性取决于系统的范围 -
判断是否把一个领域概念建模为实体:
当它被替换为另一个具有同样属性值的对象时,是否影响业务的正确性?
这些概念是否有状态的变化,如“使用前”“使用后”“被确认”等?
如果答案是其中一条或两条,则概念应建模为实体 -
(2)实体的实现
1)基础模型。在类图上,用自定义关键字<>来标识这个类是实体。
实体一般都会继承一个实体基类,实体基类一般位于类继承结构的最上端。
从领域概念诞生的子类,要继承体现自己对应领域概念的抽象类,而不用继承实体基类
2)代码。实体的本质特征是通过身份(标识符)来判断是否为相同的事物 -
值对象
通过其特性所定义的,它不需要身份,相同特性的值对象是完全等价的
值对象拥有以下领域特征:
总是与另一个对象相关联,用于描述或度量另一个领域对象。
将不同的相关属性组合成一个概念集体。
可以被另一个值对象替换,不会影响业务的正确性。
没有任何状态,它本身其实就是不可变的(一个值对象在创建之后便不能被改变了)。值对象总是与一个或多个实体类型相关联,可以作为一个属性容器描述和度量实体的某些特征。
比如邮寄地址,它将省、市、区、小区、楼栋、门牌、电话等相关属性组合在一起,用来描述实体“顾客”的某个特征 -
(2)值对象的实现
1)基础模型。可以用自定义关键字<>来标识一个类是值对象,
2)代码。通过所有属性值相同来判断相等的,而不是特定的身份标识符 -
实体与值对象的比较
-
两者的不同点
(1)两者相等的判定逻辑不一样
实体对象而言,只要身份一致,即标识符一致,那么它就是同一个事物
值对象没有标识符,它们之间所有的属性值一致才能判定为是同一个事物
(2)两者的生命周期不同
实体有状态变化,为连续统一体。因为有ID相关联,它们拥有“历史”,串联起一系列数据,
描述了发生在它们身上的事情,以及它们整个生命周期中的变化值对象的生命周期为零,我们可以随时创造和摧毁它们。这是可互换的必然结果。比如一张一元的钞票和另一张一样,那何必费心区分它们呢?我们可以用刚刚实例化的对象替换现有对象,然后完全忘记它值对象不能独立存在,它们应该始终属于一个或多个实体。值对象表示的数据仅在它所指的实体的上下文中才有意义。如人和钱的例子中,“多少钱”没有任何意义,因为它没有传达正确的上下文。只有问题变成“付款有多少钱”或“退款有多少钱”、“你有多少钱”或“我有多少钱”才是完全有效的
(3)两者在持久化机制上的区别和联系
领域中的值对象也不需要自己的表,不要为值对象创建单独的表,只需将它们内联到父实体的表中即可
-
领域服务
(1)领域服务的领域特征
领域服务表示一个无状态的操作,之所以给其单独建模,是因为这类操作不适合放在实体或值对象中。
强行放入会破坏上述模型的内聚性,并且也增加了用户发现服务的难度如果一个操作需要的信息超出了一个类能提供的数据的范围,那么它就不适合放在该类中
适合建模为领域服务的操作特征总结如下:
操作过程涉及多个领域对象。
对领域对象进行转换。
以多个领域对象作为输入,结果产生一个值对象(如统计计算逻辑)。
操作本身是无状态的。
领域服务包含业务规则,应用服务则是满足用例和通用规则
(2)领域服务的实现
用一个单独的服务类来封装操作
为操作独立出一个接口,然后让实现类来实现该接口(取决于你对操作多态性的需要,即是否有不同的操作逻辑需要灵活地替换)