IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> DDD防腐层设计 -> 正文阅读

[Java知识库]DDD防腐层设计

DDD防腐层设计?

本文主旨

  • 防腐层核心思想。

  • 防腐层设计思路。

  • 门面和适配器实现防腐层。

防腐层(Anti-Corruption Layer)思想:通过引入一个间接的层,就可以有效隔离限界上下文之间的耦合。防腐层往往属于下游限界上下文, 用以隔绝上游限界上下文可能发生的变化。

即使上游发生了变化,影响的也仅仅是防腐层中的单一变化点,只要防腐层的接口不变,下游限界上下文的其他实现就不会受到影响。

缺点是代码会重复,但解耦彻底。

防腐层设计:比如用户订单微服务本地增加一个订单支付Service的Feign接口,这样用户订单Service就像本地调用一样调用支付Service,再通过这个feign接口实现远程调用,这样的设计叫做防腐层设计。

防腐层实现

防腐层用于隔离变化,代码落地方面可结合门面模式 + 适配器模式来实现。

?

门面模式可简单理解为将多个接口进行封装,对调用层提供更精简的调用。

?

适配器模式可简单理解为将外部系统提供的不兼容接口,转换为内部合适的接口。

门面模式(外观模式) Facade Pattern

隐藏系统的复杂性,并向客户端提供一个可以访问系统的接口。

优点:

  1. 减少系统相互依赖;

  2. 提高灵活性;

  3. 提高了安全性。

缺点:

  1. 不符合开闭原则。

应用场景:

  1. Java的三层开发模式;

  2. Tomcat RequestFacade类就使用了外观模式。RequestFacade是对Request类封装,屏蔽内部属性和方法,避免暴露。

举例:定义了3个接口,客户端正常调用实现的话,需要依赖三个实现类,调用其方法。用外观模式后,定义外观类Facade,其内部实例化了三个实现类的对象。客户端直接调用Facade类来完成调用即可。

适配器模式 Adapter Pattern

主要是为了在不改变原有接口的基础上,适配新的接口。使原本接口不兼容的类可以一起工作。

适配器种类:

  • 类适配器:需要继承被适配器类实现目标接口。

  • 对象适配器:不继承,new一个对象实例。

  • 接口适配器:有些适配方法不需要全部实现,可创建抽象类实现接口中全部方法。

优点:

  1. 可以让任何两个没有关联的类一起运行;

  2. 提高了类的复用;

  3. 增加了类的透明度;

  4. 灵活性好。

缺点:

  1. 过多使用适配器,会让系统内部变的复杂。比如明明调用的A接口,但内部被适配成了B接口的实现。

应用场景:springmvc中DispatcherServlet类的doDispatch方法用到了适配器模式。通过request获取handler,通过handler获取适配器类。

防腐层简单案例

在某个业务场景中,会有很多的命令触发相关事件,这些事件会被作为任务去执行。执行后会调用通知service来完成通知(短信通知、企业微信通知、H5端通知、公众号通知等等)。

项目初期所有的业务逻辑都在一个服务内,此时TaskService直接引用NoticeService即可完成通知服务的调用。

随着需求的不断迭代,后期项目越来越复杂,单应用内包含的子域越来越多,每个子域也会有更多的职责。

像通知服务不仅仅内部服务会调用,也会提供第三方服务调用。为了解耦合,此时把通知作为单独的服务拆分出去,把通知相关的业务逻辑限定在通知子域内。

此时拆分有两种方式:

  1. 根据通知的业务属性独立为单独的服务,作为通用域存在。

  2. 不拆分服务,只拆分package,把通知相关的逻辑限制在通知的package内,假如后面需要独立服务部署,是可以更快的分离出去。

拆分后为了不影响原来的TaskService调用逻辑,采用防腐层的思想,用门面模式封装调用第三方的规则,用适配器模式完成不同的消息通知方案。

通知传输对象

@Data
public?class?NoticeDTO?{

????/**
?????*?姓名
?????*/
????private?String?name;

????/**
?????*?手机号
?????*/
????private?String?mobile;

????/**
?????*?消息内容
?????*/
????private?String?content;

????/**
?????*?消息类型
?????*/
????private?Integer?type;
????
????......
}

任务传输对象

@Data
public?class?TaskDTO?{

????/**
?????*?姓名
?????*/
????private?String?name;

????/**
?????*?手机号
?????*/
????private?String?mobile;

????/**
?????*?消息内容
?????*/
????private?String?msg;

????/**
?????*?消息类型
?????*/
????private?Integer?type;
????
????.....
}

定义通知门面类完成DTO对象的转换,封装Http调用的代码。

通知门面类

public?class?NoticeFacade?{

????public?Object?weChatNotice(TaskDTO?taskDTO)?{
????????NoticeDTO?noticeDTO?=?this.convert(taskDTO);

????????Object?obj?=?this.send(noticeDTO);
????????//补全taskDTO属性

????????return?taskDTO;
????}

????public?Object?send(NoticeDTO?noticeDTO)?{
????????//构建http请求体
????????HttpRequest?request?=?HttpRequest.newBuilder()
????????????????.uri(URI.create("https://www.baidu.com/"))
????????????????.timeout(Duration.ofSeconds(20))
????????????????.header("Content-Type",?"application/json")
????????????????//.POST(HttpRequest.BodyPublishers.noBody())
????????????????.GET()
????????????????//.POST(HttpRequest.BodyPublishers.ofFile(Paths.get("file.json")))
????????????????.build();

????????//构建http客户端
????????HttpClient?client?=?HttpClient.newBuilder()
????????????????.version(HttpClient.Version.HTTP_1_1)
????????????????.followRedirects(HttpClient.Redirect.NORMAL)
????????????????.connectTimeout(Duration.ofSeconds(20))
????????????????//.proxy(ProxySelector.of(new?InetSocketAddress("https://www.baidu.com",?80)))
????????????????//.authenticator(Authenticator.getDefault())
????????????????.build();

????????//同步调用
????????HttpResponse?response?=?client.send(request,?HttpResponse.BodyHandlers.ofString());

????????.....
????????Object?obj?=?response.body();
????????return?obj;
????}

????//传输实体转换
????private?NoticeDTO?convert(TaskDTO?taskDTO)?{
????????NoticeDTO?noticeDTO?=?new?NoticeDTO();
????????noticeDTO.setContent(taskDTO.getMsg());
????????......

????????return?noticeDTO;
????}
}

通知适配器省略相关逻辑,为适应扩展需求可参考spring 源码中适配器用法。此处定义了微信通知的调用。

通知对象适配器

public?class?NoticeAdapter?{

????public?NoticeFacade?noticeFacade;

????public?TaskDTO?toPush(TaskDTO?taskDTO)?{

????????Object?obj?=?noticeFacade.weChatNotice(taskDTO);
????????......

????????return?taskDTO;
????}
}

任务Service像以前一样调用通知方法,只不过引用的适配器对象,由适配器完成后面的实现。

此时由NoticeAdapter + NoticeFacade 完成通知逻辑的防腐。后面可变的修改隔离在防腐层代码中。

任务Service

public?class?TaskService?{

????private?NoticeAdapter?noticeAdapter;

????public?void?run(TaskDTO?taskDTO)?{
????????this.noticeAdapter.toPush(taskDTO);
????????......?处理后续逻辑
????}
}

总结

防腐层主要用于上下文映射(不同领域之间的协作)的解决方案。

其目的还是为了隔离上游服务的可变性,降低影响范围,以更小的可能变更代码。

可关注【阿飞技术】公众号

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:42:45  更:2022-09-24 20:46:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:13:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码