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分层架构,但你却从来没有使 ...
随机推荐
- Python进阶——什么是上下文管理器?
在 Python 开发中,我们经常会使用到 with 语法块,例如在读写文件时,保证文件描述符的正确关闭,避免资源泄露问题. 你有没有思考过, with 背后是如何实现的?我们常常听到的上下文管理器究 ...
- spring整合sharding-jdbc实现分库分表
1.创建两个库,每个库创建两个分表t_order_1,t_order_2 DROP TABLE IF EXISTS `t_order_1`; CREATE TABLE `t_order_1` ( `i ...
- 私有Maven仓库安装和使用
安装 这里选择安装的是windows平台,linux安装类似,下载可能要梯子 官网下载页 https://help.sonatype.com/repomanager2/download 下载链接 ht ...
- 10天,从.Net转Java,并找到月薪2W的工作(一)
大学学的是Java,但是工作一直都是.Net方面的工作. 看到各种各样的大厂都是招Java,工资比.Net高,岗位多.而.Net大多都是维护老系统,传统行业这类的工作.甚至发现工作经验不足我一半的薪水 ...
- C# 9 新特性 —— 增强的 foreach
C# 9 新特性 -- 增强的 foreach Intro 在 C# 9 中增强了 foreach 的使用,使得一切对象都有 foreach 的可能 我们来看一段代码,这里我们试图遍历一个 int 类 ...
- mybatis-plus 自定义SQL,XML形式,传参的几种方式
mybatis-plus 自定义SQL,XML形式,传参的几种方式 前提说明 所涉及文件 传参类型说明 1.Java代码中使用QueryWrapper动态拼装SQL 2.简单类型参数(如String, ...
- js对比两个时间的大小
/** * 时间对比 开始=结束返回0;开始>结束返回-1;开始<结束返回1 */ function dateComparison(date1,date2){ var start =new ...
- TurtleBot3 Waffle (tx2版华夫)(4)笔记本与TX2的通信
4.1. 使用vnc控制华夫Turbot3-Tx2开发板 1) 电脑端安装vnc viewer,您可以选择应用商城下载安装即可: 2) 下载后打开,键入Turbot3的ip à回车à选择连接: 3) ...
- (转) 增加 header 参数,spring boot + swagger2(springfox)
1 @Configuration 2 @EnableSwagger2 3 public class Swagger2 { 4 @Bean 5 public Docket createRestApi() ...
- java实现发送短信验证码
java实现短信验证码发送 由于我们使用第三方平台进行验证码的发送,所以首先,我们要在一个平台进行注册. 在这里我选择是秒嘀科技,因为新人注册会赠送十元,足够测试使用了. 注册完成后,我们需要获取自己 ...