大话领域驱动设计——领域层

概述

在DDD中,业务逻辑主要分布在领域层和应用层两层,他们包含不同的业务逻辑。这一篇,我们先对领域层做详细的讲解分析。

f6864ef0a47e96f3326bfafe676d51f3.png

领域层实现了领域或系统的,与用户界面上的用户交互(用例)无关的核心业务逻辑。

总览

a1f6bc9eb20d813a9ff095f5964beadd.png

领域层主要包含以下组件:

实体(Entity)实体是一个具有自己的属性(状态、数据)和实现在这些属性上执行的业务逻辑的方法的对象。实体由其唯一标识符(Id)表示。具有不同id的两个实体对象被视为不同的实体。

聚合和聚合根Aggregate&Aggregate Root聚合是通过集合根对象绑定在一起的对象集(实体和值对象)。聚合根是具有一些附加职责的实体的特定类型。

值对象Value Object值对象是另一种由其属性而不是唯一的Id来标识的域对象。这意味着两个具有相同属性的值对象将被视为相同的对象。值对象通常被实现为不可变对象,而且大多数值对象都比实体要简单得多。

域服务Domain Service领域服务是一个实现域的核心业务规则的无状态服务。它依赖于多个聚合(实体)类型或某些外部服务,用于领域逻辑的实现。

仓储Repository接口:仓储是一个类似于集合的接口,它被领域层和应用层用于访问数据持久化系统(数据库)。它对业务代码隐藏了DBMS的复杂性。领域层包含仓储的接口声明。

规约(Specification)规约用于为实体和其他业务对象定义已命名的、可重用的且可组合的过滤器。

域事件Domain Event领域事件是在领域特定事件发生时以松散耦合的形式通知其他服务的一种方法。

6989b5c66bdf94194dfce671608df44c.png

在ABP框架下,领域层包含以下两个项目:

Domain是包含所有组件(实体、聚合根、值对象、领域服务、规约、存储库接口等)的基本领域层。‍

Domain.Shared是一个轻量的项目,它包含了属于领域层的一些类型,但与所有其他层共享。例如,它可能包含一些与域对象相关的常量和枚举,但需要被其他层重用。

实现细节

1

实体

d99bf0154481c8f78eeb25695586bb10.gif

在ABP中,所有的实体类均需实现ABP框架中定义的接口 IEntity 。ABP中将实体分为两种用法:有默认主键(Id)的实体和没有默认主键的实体。

dcdd060a5667d54cc176a6a617091172.gif

有默认主键的实体在 IEntity 接口基础上封装了 IEntity<TKey> 接口,其中,定义了TKey类型的主键,名称为Id。其默认实现类继承自 Entity<TKey> 。我们使用时,需以泛型方式定义主键的类型。

ecfe3141412cdaa5461b99f19d87432d.gif

无默认主键的实体类直接实现IEntity接口,其默认实现类继承自 Entity ,在 Entity 中定义了虚方法 object[] GetKeys() 。该方法用于设定一个或多个属性为主键。使用无默认主键的实体时,我们必须实现GetKeys方法指定该实体类对应数据库表的主键。

0f5d30de4891cbc2dfc16c17e370159d.gif

在ABP中,对于实体定义了默认增删改操作的审计属性,通过 ICreationAuditedObject , IModificationAuditedObject 和 IDeletionAuditedObject 三个接口进行约束,分别包含对添加(添加人,添加时间),修改(修改人、修改时间),删除(删除人、删除时间、是否被软删除)操作记录的审计属性。ABP为ICreationAuditedObject接口创建了默认实现基类 CreationAuditedEntity ,同时还创建了包含以上三个接口所有实现的基类 FullAuditedEntity , CreationAuditedEntity 和 FullAuditedEntity 均包含有默认主键和无默认主键两种用法,以是否定义泛型来区分。

db11c5c0a0283e6c1265fa1fe4f9c364.gif

ABP中定义了 ISoftDelete 接口,其中包含 IsDeleted 属性,表示该条数据是否被软删除。当实体实现ISoftDelete接口时,ABP的仓储会自动将删除方法转为软删除,即只将IsDeleted属性设置为true,使其部不被查询到,但并不在数据库中对数据进行物理删除。

2

聚合根

b75a868ee3b7b17082a949e48dba0b60.gif

在ABP中聚合根需实现I AggregateRoot ,其默认基类为 AggregateRoot ,同时 AggregateRoot 也实现了 IEntity 接口。 IAggregateRoot 本身未包含任何属性或者方法的声明,其主键声明继承自IEntity接口。

3317f3645d7b31d145de429e82a5f413.gif

和实体类相同,聚合根也定义了有默认主键和无默认主键两种用法,通过是否传入泛型来进行区分。

22d1d1076000390e2e2a27d07d41efa9.gif

聚合根也可以实现 ICreationAuditedObject ,  IModificationAuditedObject 和 IDeletionAuditedObject 对增删改操作进行审计记录,其中实现接口 ICreationAuditedObject 的基类为 CreationAuditedAggregateRoot ,实现所有审计接口的基类为 FullAuditedEntity 。

3

值对象

501c04870e9f83d37a48fd8014e69584.gif

值对象的定义相对来说非常简单,在ABP中,定义了值对象的基类  ValueObject  ,定义值对象必须继承ValueObject  ValueObject 并实现ValueObject中定义的抽象方法 GetAtomicValues() 。

4e05c32f8fa526dd4c20e813f31d6bbb.gif

GetAtomicValues 方法用于检查两个值对象是否相等,其用法为通过 yield return 返回一组属性,表示如果两个值对象这些属性值都相等,则这两个为相等的值对象。示例代码如下:

protected override IEnumerable<object> GetAtomicValues() {    yield return Street;    yield return CityId;    yield return Number; }

4

领域服务

c7d26fd7796c8b664a6797caf1a19e81.gif

领域服务的接口和实现均包含在领域层Domain项目中,其中领域服务接口声明继承自ABP提供的 IDomainService 接口,领域服务实现类继承自ABP提供的 DomainService 类。

705f7cbbdd6e000118383cc61718b416.gif

在 IDomainService 接口中未声明任何属性和方法,我们如果需要用到领域服务,可完全依据自己的需求定义其中的内容。

2ae9b1ec76f42bffa1678baae0e09202.gif

在ABP框架中,领域服务通过自动依赖注入的方式以瞬态生命周期被注册到IOC容器中,即每次使用都会生成一个新的实例。我们只需要保证其所在类库中含有继承自 AbpModule 的模块定义类,即可实现自动依赖注入。

5

仓储接口

bfc18922adedee800ab47b2e81ff5d27.gif

在领域层Domain项目中,只会声明仓储的接口,其实现需要在基础设施层的EntityFrameworkCore项目中编写。

adccfb30240008174b9760243dab2780.gif

ABP框架已经为我们提供了默认的仓储接口和实现,在大多数情况下,我们不需要编写任何仓储接口或实现类的代码,只需要在使用时注入 IRepository<TEntity, TKey> ,其中的两个泛型分别为实体/聚合根的类型和主键数据类型。

b703a67b9f718b113d156c8550142d98.gif

如果我们需要自定义仓储,则在Domain层定义其接口声明,仓储接口声明需要继承自 IRepository 接口。

6

规约

5c60c9487a3eadfa28d60e0eddc1d23d.gif

ABP提供了规约的接口 ISpecification<T> 和实现类基类 Specification<T> ,其中泛型为需要约束的实体或聚合根的类型。

c1e533cec5d579169754b45a2c76760e.gif

编写规约时必须实现 ISpecification 接口中定义的 ToExpression 方法,该方法用来声明规约中数据约束的表达式。

04df26045f39a23d0a52f8dd82700635.gif

同时, ISpecification 接口中还定义了 IsSatisfiedBy 方法,用于判断一个对象是否满足此规约,在 Specification 类中已提供了此方法的默认实现。

7

领域事件

9c69ff32d4e7d3d1ce38169c4f438be2.gif

ABP提供了本地事件总线和分布式事件总线两种方案,其中本地事件总线常用于我们DDD中传统意义的领域事件实现,而分布式事件总线常用于分布式或微服务系统的事件处理。

299ae0b53aede7759bd17afda4e49d4a.gif

ABP本地领域事件使用主要分为订阅和发布两个部分:

ef875f76f79d2234b817762668382a4b.gif

发布和订阅的事件或对应关系以其传输的数据类型为区分。对于每种事件,我们都需要单独定义一个事件类型的简单类(ABP未提供统一基类,直接继承自Object即可)用于存放传输的数据,即使不需要传输数据,我们也要定义一个空类来区分事件类型。该类型命名通常以Event结尾。

84be11402024ce1957cc5855a78f940b.gif

在DomainService、ApplicationService、Controller等可以使用依赖注入的组件中,我们可以注入 ILocalEventBus 接口并调用 PublishAsync 方法来发布事件,在Entity和Aggregate Root中无法使用依赖注入,ABP官方给他们提供了一个基础方法 AddLocalEvent 用于发布事件。

561425a67114551a8e5f7d44fdbfeb46.gif

在订阅事件时我们需要定义一个类,实现 ILocalEventHandler<T>  其中的泛型为前面所说的事件类型定义,并实现接口中的 HandleEventAsync 方法用于处理事件。

END

a7c4beee43dd6df1e2230a10f670fa11.png

625dc2c371b6ba58539c75465dd25fd2.png

关注我获得

更多精彩

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/286822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【北斗】北斗卫星导航系统(BDS)介绍

一、概述 北斗卫星导航系统(以下简称北斗系统)是中国着眼于国家安全和经济社会发展需要,自主建设运行的全球卫星导航系统,是为全球用户提供全天候、全天时、高精度的定位、导航和授时服务的国家重要时空基础设施。 北斗系统提供服务以来,已在交通运输、农林渔业、水文监…

Android之解决VideoView控件的进度条位置摆放问题和打开播放黑屏问题

1 问题 VideoView控件如何配合MediaController使用,就会显示进度条,但是位置摆放在最底部,不是我们想要的结果 2、基本使用 private var mMediaController:MediaController? = nullfun playVedio() {mMediaController = MediaController(this as Activity)trashVideoView…

Snmp linux

http://blog.csdn.net/youngqj/article/details/7311849 http://blog.csdn.net/howema/article/details/4182408 http://my.oschina.net/yisenn/blog/14626转载于:https://www.cnblogs.com/diyunpeng/p/5720952.html

正则验证金额大于等于0,并且只到小数点后2位

2019独角兽企业重金招聘Python工程师标准>>> ^(([0-9]|([1-9][0-9]{0,9}))((\.[0-9]{1,2})?))$ 转载于:https://my.oschina.net/u/934148/blog/528688

我结婚了,我要用什么做个邀请函呢?【iVX无代码YYDS 06】

作者简介 作者名&#xff1a;1_bit 简介&#xff1a;CSDN博客专家&#xff0c;2020年博客之星TOP5&#xff0c;InfoQ签约作者、CSDN新星导师&#xff0c;华为云享专家。15-16年曾在网上直播&#xff0c;带领一批程序小白走上程序员之路。欢迎各位小白加我咨询我相关信息&#…

【专升本计算机】计算机文化基础练习题(选择题300道附答案)

专升本计算机文化基础练习题 1、 世界上第一台电子计算机诞生于 ______A_ 。 A . 20 世纪 40 年代 B . 19 世纪 C . 20 世纪 80 年代 D . 1950 年 2、 世界上第一台电子计算机是 1946 年在美国研制成功的,该机的英文缩写名是 ___A__ 。 A . ENIAC B . EDVAC C…

《微软云计算Microsoft Azure部署与管理指南》即将上市!!!

大家好&#xff0c;本人新作《微软云计算Microsoft Azure部署与管理指南》即将与广大读者见面&#xff0c;由电子工业出版社出版。希望大家能关注此书&#xff0c;并推荐给身边的好友和技术人员。 众所周知&#xff0c;Microsoft Azure是专业的国际化公有云平台, 是微软研发的公…

如何用SQL来检测文件是否存在

工作中&#xff0c;我们经常需要检查上传的文件是否存在&#xff0c;用户上传的头像是否存在&#xff0c;等等。 有没有办法直接用SQL来查询呢&#xff1f; 请直接看代码&#xff1a; /************************************************************ * Create By Jacky * T…

如何解决分布式日志exceptionless的写入瓶颈

我们都知道在分布式日志当中&#xff0c;exceptionless客户端是把日志写到Elasticsearch数据库&#xff0c;就像我们把数据写入到关系数据库一样&#xff1b;既然是写入&#xff0c;那么在短时间大数据量的情况下&#xff0c;写入就会涉及到效率的问题&#xff1b;首先我们看下…

iVX 基础

1.1 iVX 线上集成环境进入 点击 连接 或通过浏览器输入网址 https://editor.ivx.cn/ 进入线上集成开发环境。 进入 在线集成开发环境 后&#xff0c;可点击右上角 登录/注册 进行帐号登录或者注册。登录账户 后在进行项目开发时会自动保存项目开发进度。 [外链图片转存失败…

关于有序二维矩阵查找和字符串替换的两道算法题

最近看一本书上写到的两个面试题 于是实现了一下 感觉思路很好,大牛略过 : 1、对于一个二维矩阵,从左到右 从上到下 都是递增的,如何判断一个值是否在矩阵内部?&#xff08;C实现 实现复杂度 O(n)&#xff09; bool FindInTwoDimensionalMatrix(int*pMatrix,int iRows,int i…

Maven实战:pom.xml与settings.xml

pom.xml与settings.xml pom.xml与setting.xml&#xff0c;可以说是Maven中最重要的两个配置文件&#xff0c;决定了Maven的核心功能&#xff0c;虽然之前的文章零零碎碎有提到过pom.xml和settings.xml里面的内容&#xff0c;但都是大略带过&#xff0c;学习与研究地并不细致&am…

Android之靠谱的把图片和视频插入手机系统相册

1 需求 把图片和视频插入手机系统相册,网上查了下基本上很乱,没几个靠谱的。 2 结果爆照 3 思路 图片插入系统相册(可以直接插入系统相册,但是我这里多做了一步就是先把图片拷贝到了一个目录再插入系统相册) 视频插入系统相册(先把视频拷贝到MIUI目录,然后再…

【专升本计算机】计算机操作系统练习题(选择判断名词解释简答)

一、填空 1. 操作系统为用户提供三种类型的使用接口,它们是 命令方式 和 系统调用 和 图形用户界面 。 2. 主存储器与外围设备之间的数据传送控制方式 ( I/O 控制方式) 有 程序直接控制、中断驱动方式、 DMA 方式 和 通道控制方式。 3. 在响应比最高者优先的作业调…

C# WPF 实现Tab页动态增减

概述Tab页面是一个很常用的控件&#xff0c;针对页面固定的场景&#xff0c;直接给Item进行数据绑定就行&#xff0c;如下所示&#xff1a;<dx:DXTabControl cal:Message.Attach"[Event Loaded][TabControl_Loaded($source,$eventArgs)]"><dx:DXTabItem Hea…

2014 网选 上海赛区 hdu 5047 Sawtooth

题意&#xff1a;求n个M型的折线将一个平面分成的最多的面数&#xff01; 思路&#xff1a;我们都知道n条直线将一个平面分成的最多平面数是 An An-1 n1 也就是f(n) (n*n n 2)/2 对于一个M型的折线呢&#xff1f;它有四条线&#xff0c;但是由于三个顶点的关系导致划分的平…

二、基础(IVX快速开发手册)

二、基础 通过本节你将了解 iVX 所支持应用的创建方法。 文章目录二、基础2.1 iVX 线上集成环境进入2.2 创建项目2.3 选择项目类型2.3.1 WebApp/小程序/原生应用2.3.2 微信小游戏2.3.3 微信小程序&#xff08;原生组件&#xff09;2.1 iVX 线上集成环境进入 点击 连接 或通过…

【专升本计算机】经典Office 2003专升本复习题(Word、Excel、PowerPoint)

经典Office 2003专升本复习题(Word、Excel、PowerPoint) 一、Word 2003 1. 启动 Word 是指: 将 Word 从硬盘中调入主存执行 2. 菜单栏: 文件( F )、编辑( E )、视图( V )、插入( I )、格式( O )、工具( T )、表格( A )、窗口( W )、帮主( H ) 3. …

Android之TabLayout+ViewPager2+FragmentStateAdapter实现带数字变化的TAB选项

1 问题 TabLayout+ViewPager2实现带数字变化的TAB选项,然后左边滑动或者点击上面的Tab切换fragment不能刷新 2 结果爆照 3 代码实现 layer_tab_indicator.xml <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="h…

slq2000数据库升级到sql2012

看到标题&#xff0c;估计有同行笑了&#xff0c;这年代还有用sql2000的&#xff1f;真的有&#xff0c;最近单位服务器数据迁移升级&#xff0c;将数据库迁移到新服务器后&#xff0c;发现数据全是2000的&#xff0c;无法直接导入到sql2012。没办法&#xff0c;只能先将数据库…