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面试中的设计模式,搞懂这些就足够了
1.什么是设计模式? 设计模式是经过总结.优化,对我们经常遇到的一些编程问题的可重用的解决方案.设计模式不同于类或库可直接作用于代码.相反,它更为的高级,是一种必须在特定的情形下实现的方法模版. 2. ...
- PhPMyadmin拿Shell
phpmyadmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具, --百度百科 1.入口寻找 目录扫描: 根据Linux对大小写敏感判断目标服 ...
- Redis 设计与实现:字符串 SDS
本文的分析没有特殊说明都是基于 Redis 6.0 版本源码 redis 6.0 源码:https://github.com/redis/redis/tree/6.0 在 Redis 中,字符串都用自 ...
- [leetcode]79.Search Word 回溯法
/** * Given a 2D board and a word, find if the word exists in the grid. The word can be constructed ...
- 基于websocket的netty demo
前面2文 基于http的netty demo 基于socket的netty demo 讲了netty在http和socket的使用,下面讲讲netty如何使用websocket websocket是h ...
- VScode中配置C++运行环境
目录 VScode中配置C++运行环境 1. 哪些插件 2. 配置开始 3. 编写代码并运行 VScode中配置C++运行环境 关于安装mingw的教程,网络上已经有很多了,这里不再赘述,下面就看VS ...
- 浅谈java中的枚举类型(转)
用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...
- eclipse的相关操作和使用快捷键
修改字体Window->preferences->General->Appearance->ColorsandFonts ->Basic->text Font 在e ...
- MyArray框架搭建与实现
#include<iostream> using namespace std; template<class T> class MyArray { public: //构造函数 ...
- flume将数据写入各个组件
一.flume集成hdfs,将数据写入到hdfs a1.sources = r1 a1.sinks = k1 a1.channels = c ...