在DDD中,”标识符”用来唯一定位一个对象,在数据库中我们一般用表的主键来实现标识符。
当谈到标识符的时候,我们是站在业务的角度思考问题,而谈到主键的时候,我们是站在技术的角度思考问题。
在DDD中大量存在着这样一类对象,它们拥有唯一的标识符,标识符的值不会改变,而对象的其他状态则会经历各种变化。
这样的对象可能会被持久化地保存在存储设备中,即使软件重启,我们也可以把持久化在存储设备中的对象还原出来,我们把这样的对象称为实体类(entity)。
标识符是用来跟踪对象状态变化的,一个实体类的对象无论经历怎么的变化,只要看到标识符的值没有变化,我们就知道它们还是那个对象。
在具体实现DDD的时候,实体类一般的表现形式就是EF Core中的实体类,实体类的ID属性一般就是标识符,但是只要ID不变,我们就知道前后两个对象指的是同一个对象。
我们可以把实体类的对象保存到数据库中,也可以把它从数据库中读取出来。
在DDD中还存在着一些没有标识符的对象,它们也有多个属性,它们依附于某个实体类对象而存在,这些没有标识符的对象叫做值对象。
同一个值对象不会被多个实体类对象引用;
值对象一般是不可变的,也就是值对象的属性不可以修改。
因此如果我们要修改实体类的一个值对象属性,我们只能创建一个新的值对象来替换旧的值对象。
比如,在电子地图系统中,”商家”就是一个实体类,该实体类包含营业执照编号、名称、经纬度位置电话等属性。
一个商家的营业执照编号是不可以修改的,而商家的名称、经纬度位置、电话都是可以修改的,只要两个商家的营业执照编号一样,我们就认定两个商家是同一家,因此营业执照编号就可以看作标识符。
而经纬度位置就是一个值对象,经纬度位置的经度和纬度对象包含”经度”和”纬度”两个属性,经纬度位置没有标识符,而且经纬度的经度和纬度两个属性也不会被修改,如果商家搬家了,我们只要重新创建一个新的经纬度位置的对象,然后重新赋值商家的经度和纬度属性就可以了。
当然,我们也可以取消经纬度位置这个值对象属性,直接改为经度、纬度两个属性,也就是商家实体类包含营业执照编号、名字、经度、纬度、电话等属性,但是把经度和纬度作为一个值对象更能体现它们的整体关系。
实体类帮助我们跟踪对象的变更,而值对象则帮助我们把多个相关属性当作一个整体。