值对象 Value Object

1 理解值对象

讨论值对象,先简单介绍下实体,通俗的理解:实体是由唯一标识和一系列属性构造的类,实体的核心是用唯一标识来定义的,而不是通过属性来定义的。即使属性完全相同也可能是两个不同的对象。实体本身是有状态的,有生命周期,实体本身会提箱相关的业务行为,业务行为会使实体属性或状态发生改变和影响

值对象本身是无状态的,不可变,没有唯一标识,从这个层面上来讲,值对象可以理解为实际的Entity对象的一个属性的结合,该值对象附属在一个实际的实体对象上面。值对象本省不存在一个独立的生命周期,也一般不会产生独立的行为
值对象 Value Object_第1张图片
如上图所示,一个聚合根通常是由多个属性构成,比如Order这个实体(在这里是聚合根)由一系列的属性构成:唯一标识ID,OrderDate,OrderItems ,Address等,其中Address是一个对象引用,它有Street,City,country等属性构成,但是并没有唯一标识,因此Address被模型化为一个值对象。

2 值对象特性

没有唯一标识
不变性

在值对象中,不关心标识,只要我们能确定值对象的属性值都一样,我们就可以说这两个值对象是相同的
比如说两个学生的家庭地址(省市县街道门牌号)是一样的,我们就可以认为是同一个地址,者就是相等性比较。
如果学生在修改地址的时候,无论修改的省或者市或者县,我们不关心改了多少,而是 将整个值对象覆盖,这就是值对象的不变性和可替换性

更好的表达业务概念

例如:有一个Student表,有 Name,Age,Gender,Province,City,Street 等属性
可以有两种实现方式:
方式一:将这些属性全部生命在一个Student实体中
方式二:将Provice City Street等表达地址的信息独立出来,包装成一个值对象

复制代码
    public class Student : Entity
    {
        //.....其他属性

        /// 
        /// 地址外键
        /// 
        public Address Address { get; private set; }
     
    }
    /// 
    /// 地址
    /// 
    public class Address :Entity {/// 
        /// 省份
        /// 
        public string Province { get; private set; }
        /// 
        /// 城市
        /// 
        public string City { get; private set; }

    }

显然方式二更能够清楚的表达业务

当决定一个领域概念是否是一个值对象的时候,需要考虑是否具有以下特性:

1 它描述了领域中的一个东西
2 可以作为一个不变量
3 当它改变时,可以用另一个值对象替换
4 可以和别的值对象进行相等性比较

3 实体和值对象区别

1 实体有标识,值对象没有
2 相等性测试方式不同。实体根据标识判断,值对象根据内部所有属性值判断
3 实体匀速变化,值对象不允许变化
4 持久化的映射方式不同。实体采用单表继承、类表继承、具体表继承来映射类层次结构,而值对象采用嵌入式或序列化大对象方式映射

4 EF/EFCore实现值对象

1.EF中实现值对象和普通entity没有什么区别,因为需要持久层到数据库中,仍然需要唯一标识。
2.EFCore 对值对象实现了良好的支持。
EFCore1.1使用值对象需要在DbContext中为值对象指定隐藏的唯一标识
EFCore2.0及以后版本出现了 owned entity type (自引用实体类型),需要在实体的Configuration中配置一下即可,如下:

值对象是单个对象情况:
值对象 Value Object_第2张图片

值对象是List的情形:
值对象 Value Object_第3张图片

参考:
微软官方文档
大神总结

你可能感兴趣的:(概念澄清,DDD)