DDD的实体、值对象、聚合根的基类和接口:设计与实现
1 前置阅读
在阅读本文章之前,你可以先阅读:
- 什么是DDD
2 实现值对象
值对象有两个主要特征:它们没有任何标识。它们是不可变的。
我们举个例子:小明是“浙江宁波”人,小红也是“浙江宁波”人,小王是“浙江杭州”人,在这个例子中,我们把地址可以独立出一个值对象出来,我们会遇到了多个对象是否相同的问题,例如小明和小红的地址应该是相等,小明和小王应该是不相等,这很好理解,我们来看一下例子;
public class Address
{
public string Province;
public string City;
}
var xm = new Address { Province = "浙江", City = "宁波" };
var xh = new Address { Province = "浙江", City = "宁波" };
var xw = new Address { Province = "浙江", City = "杭州" };
Console.WriteLine(xm.Equals(xh));
Console.WriteLine(xm.Equals(xw));
让我们来看看输出结果:
False
False
这个显然不符合我们预期,我们需要重写一下Equals,确保地址值相等的情况下对象相等。
public class Address
{
public string Province;
public string City;
public bool Equals(Address obj)
{
return this.Province.Equals(obj.Province) && this.City.Equals(obj.City);
}
}
var xm = new Address { Province = "浙江", City = "宁波" };
var xh = new Address { Province = "浙江", City = "宁波" };
var xw = new Address { Province = "浙江", City = "杭州" };
Console.WriteLine(xm.Equals(xh));
Console.WriteLine(xm.Equals(xw));
让我们来看看输出结果:
True
False
这个显然符合我们预期了,接下来我们把值对象的Equals方法封装到基类中。
public abstract class ValueObject
{
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
}
public class Address : ValueObject
{
public string Province;
public string City;
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Province;
yield return City;
}
}
3 实现实体
实体主要特征:具有唯一标识。
前面我们讲到值对象将特定值都相等的对象视为相等对象,在实体中比较容易理解,标识相等的对象视为相等对象。
public abstract class Entity
{
#region IEntity Members
public abstract Guid Id
{
get; set;
}
#endregion
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
if (Object.ReferenceEquals(this, obj))
return true;
if (this.GetType() != obj.GetType())
return false;
Entity item = (Entity)obj;
return item.Id == this.Id;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
4 实现聚合根
聚合根与实体的区别,实体只在聚合内部进行操作,聚合根是对外打交道的唯一实体。我们在这里设计时聚合根需要有增改删状态字段。
public enum AggregateState
{
Added = 1,
Updated = 2,
Deleted = 3
}
public abstract class AggregateRoot : Entity
{
#region IAggregateRoot Members
public AggregateState AggregateState { set; get; }
#endregion
}
DDD的实体、值对象、聚合根的基类和接口:设计与实现的更多相关文章
- .net c#将数据库数据对象转换为实体值对象
using System; using System.Data; namespace Sunlib { public static class DataHelper { //将数据库数据对象转换为实体 ...
- DDD中的值对象如何用NHibernate进行映射
原文:DDD中的值对象如何用NHibernate进行映射 <component/>是NHibernate中一个有趣的特性,即是用来映射DDD(Data-Display-Debuger)概念 ...
- Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)
在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...
- DDD实战12 值对象不创建表,而是直接作为实体中的字段
这里的值对象如下风格: namespace Order.Domain.PocoModels { //订单地址 //虽然是值对象 但是不继承ValueObject //因为继承ValueObject会有 ...
- 把实体bean对象转换成DBObject工具类
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util ...
- [0] DDD领域驱动设计(三) 之 聚合(根)、实体、值对象
1. 聚合根.实体.值对象的区别? 从标识的角度: 聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法: 从是否只读的角度 ...
- 【转载自netfocus博客】聚合(根)、实体、值对象精炼思考总结
1.内容摘要 最近在看DDD领域驱动设计,看到实体(Entity),值对象 (Value Object),以及聚合根(Aggregate Root) 时.对他们的关系有些模糊,不清楚.于是去找了找资料 ...
- DDD 领域驱动设计-三个问题思考实体和值对象
消息场景:用户 A 发送一个消息给用户 B,用户 B 回复一个消息给用户 A... 现有设计:消息设计为实体并为聚合根,发件人.收件人设计为值对象. 三个问题: 实体最重要的特性是什么? Messag ...
- 应用程序框架实战十六:DDD分层架构之值对象(介绍篇)
前面介绍了DDD分层架构的实体,并完成了实体层超类型的开发,同时提供了验证方面的支持.本篇将介绍另一个重要的构造块——值对象,它是聚合中的主要成分. 如果说你已经在使用DDD分层架构,但你却从来没有使 ...
随机推荐
- C# 高并发、抢单解决思路
高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求.高并发相关常用的一些指标有响应时间(Respon ...
- C#读取DLL文件获取所有类
说明 调用Web.dll 文件,获取其中的所有的WebService 参考 https://blog.csdn.net/huoliya12/article/details/78873123 流程 使用 ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.6)- 串行NOR Flash下载算法(MCUXpresso IDE篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE开发环境下i.MXRT的串行NOR Flash下载算法设计. 在i.MXRT硬件那些事系列之<在串行N ...
- 【代码周边】npm是What?
社区 程序员自古以来就有社区文化: 社区的意思是:拥有共同职业或兴趣的人们,自发组织在一起,通过分享信息和资源进行合作.虚拟社区的参与者经常会在线讨论相关话题,或访问某些网站.前端程序员也有社区,世界 ...
- 对象存储Backblaze B2作为ShareX图床的Windows及安卓端配置
标题: 对象存储Backblaze B2作为ShareX图床的Windows及安卓端配置 作者: 梦幻之心星 sky-seeker@qq.com 标签: [对象存储,图床,Backblaze,Shar ...
- JVM初始化类契机
* 对于初始化只有主动使用类字段时才会初始化<br> * 除非对一个类的主动引用,否则所有引用类的方式都不会触发其初始化<br> * 主动引用有且只有以下场景:<p> ...
- 使用Modbus4J进行RTU模式串口通信
Modus协议是由MODICON(现为施耐德电气公司的一个品牌)在1979年开发的,是全球第一个真正用于工业现场的总线协议,应用非常广泛,可谓大名鼎鼎. 理论性的东西就不多介绍了,推荐一本书<M ...
- [学习笔记]尝试go-micro开发微服务<第一波>
平时项目都是基于c++,lua,node, 现在打算开始自学开发微服务; 也顺带磨砺下go和docker 前期准备 1. 有golang编程基础 本系列文章是基于有golang编程基础,有过实际开 ...
- Sqoop(三)将关系型数据库中的数据导入到HDFS(包括hive,hbase中)
一.说明: 将关系型数据库中的数据导入到 HDFS(包括 Hive, HBase) 中,如果导入的是 Hive,那么当 Hive 中没有对应表时,则自动创建. 二.操作 1.创建一张跟mysql中的i ...
- promise引用自吕大豹
去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ...