深入理解依赖反转原则(DIP)

依赖反转原则是一个比较重要的架构原则,从定义上看是要依赖于抽象,不要依赖于细节, 这个听起来很简单,好像加个接口就完事了,大家的service都是一个接口配一个实现类,是不是依赖倒置呢?很显然不是,不然今天就不用讲了

先举个例子,我们的应用会依赖很多三方的服务,DB、缓存、文件存储、短信邮件服务等等,拿缓存来说,假如使用的是redis缓存,java应用访问redis一般都会使用Jedis,如果我们的业务代码直接使用jedis,那就是依赖细节(如下图左侧),这时候公司要换技术栈,redis不用了,换成memcached,所有直接依赖JedisApi的业务代码全都得变,这就是直接依赖细节的问题:让业务层变得不太稳定

那应该怎么样保证业务层稳定呢?把依赖于细节变成依赖于抽象,业务层要的是redis吗?不!业务层要的示一个缓存服务,那就在业务层定义好缓存服务的接口,至于底层到底是redis还是memcached,业务层不关心(如上图右侧)

那谁来关心实现细节呢?外层关心,外层可以基于redis实现、也可以基于memcached实现,外层负责把业务层定义的知识(CacheService)和具体的三方服务的知识(JedisApi)互相转换、做个适配,所以这一层又叫做适配器层,如果要更换三方服务,也只是外层层变化,对业务层没有影响。

这里有个很关键的点就是,业务层定义的接口里不要有任何与细节相关的东西,不然就没有意义了,比如如果上图右侧的CacheService中还有jedis api里的东西,那就跟左侧没啥区别了,那就不叫依赖于抽象了,又变成依赖于细节了。

从依赖方向上看,上图左侧是业务层依赖于外层,右侧的依赖关系反过来了,变成了外层依赖于业务层,这就是依赖反转的本质。很明显右侧这种依赖方式,使得业务层可以保持稳定,因为规则是业务层定义的,外层只能去适配业务层定义的规则。

把依赖于redis这个例子泛化一点,应用会用到各种各样的三方服务,都是一个道理。

这样你就会发现,系统合理的依赖关系不太应该是这种从上到下的,因为领域层不应该直接依赖下面的基础设施,而应该是这种从外向内的依赖关系(这里我只画了两层同心圆,实际可能会有多层,但不妨碍我们理解)

越靠近中心,它的软件层次就越高,它越是核心业务逻辑,内部区域包含了所有的领域逻辑,而外部区域则包含了系统与外界交互的东西(比如web、rpc接口,以及数据库、文件服务、缓存这些基础设施)。不管是web、rpc还是db、cache,都是系统和外部系统交互的层,都在领域层的外层。

这里有一条非常重要的原则,就是它的依赖关系必须是外层依赖于内层,不能反过来,web层依赖于领域层,与底层设施交互的层也依赖于领域层,内层代码中不应该包含任何外层代码的知识,像类、函数、变量都不行。这样的好处很明显,业务逻辑可以保持纯净、独立,它是整个系统的核心,外层的这些东西对于业务逻辑来说都是插件,可以轻易被替换掉、并且对业务逻辑不产生影响

下面是一张六边形架构图,你会发现它要表达的意思跟前面说的是一个道理。最内层的是领域、业务逻辑,最外层的是客户端、用户、外部系统、下游基础设施

最关键的是它的依赖关系,是从外向内的,外层依赖于内层,外层了解内层的知识,反过来就不行 那怎么样保持这个依赖关系呢?用端口和适配器(所以六边形架构图又叫端口适配器架构,其实端口适配器架构更能表达它的主要思想)

端口其实就是接口,你看它端口都是在内层,意思是接口都由领域层定义,外层这一个个的适配器干嘛的呢,把外部的东西和领域层定义的互相转换,所以叫适配,这和我们前面说的是一个意思 

总结两点: 1:大家在做设计时,首先要明确内层外层的概念,核心业务逻辑就是内层的;2:有了内外层之分后,一个指导原则就是外层可以依赖内层,反过来就不行。这就是依赖反转!

tcp层需要知道http层的东西吗?ip层需要知道tcp层的东西吗?不需要!依赖反转原则应该作为大家在做架构设计时重要规则

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis关联查询(二、一对多查询)

MyBatis关联查询(二、一对多查询) 需求:查询所有用户信息及用户关联的账户信息。 分析:用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来&#xff0c…

【Amazon 实验①】Amazon WAF功能增强之实验环境准备

文章目录 1. 实验介绍2. 实验环境准备 1. 实验介绍 在真实的网络空间中,攻击者会使用大量广泛分布的僵尸网络、肉机等发起对目标的攻击。 其来源分布一般比较分散,因此难以简单防范。 本实验联合使用有多种AWS服务:Cloudfront、 Lambdaedge…

Python 字典操作函数 pop 与 popitem 的区别

更多资料获取 📚 个人网站:ipengtao.com 在Python中,字典(dictionary)是一种常用的数据结构,而对字典进行操作的函数也是开发中的重要工具。本文将深入探讨字典操作函数中的 pop 和 popitem 两个方法&…

C++的面向对象学习(4):对象的重要特性:构造函数与析构函数

文章目录 前言:将定义的类放在不同文件夹供主文件调用的方法一、构造函数与析构函数1.什么是构造函数和析构函数?2.构造函数和析构函数的语法3.构造函数的具体分类和调用方法①总的来说,构造函数分类为:默认无参构造、有参构造、拷…

word导入导出-Apache POI 和 Poi-tl

word 文件读取 使用Apache POI Word 进行读取文件 使用poi 时如果报ClassNotFoundException 等错误,请注意请求以下maven 文件的版本 Apache POI Word 说明文档:Apache POI Word 说明文档 maven 解决依赖冲突教程:https://www.cnblogs.com/…

[AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现

目录 关键词平台说明前言一、总体流程二、配置2.1 DCM and DEM2.2 BSWM2.2.1 Mode Notifaication Port2.2.2 Rules 2.3 service port2.3.1 做好DCM-->BSWM 和DCM -->SWC_Diag 的server port mapping2.3.2 做好BSWM ESH_ModeNotification 的server port mapping 2.4 SWC 中…

【Qt之Quick模块】5. QML基本类型及示例用法

QML格式 QML基本类型 在 QML 中,有以下基本类型: int:整数类型。 Rectangle {function myFunction() {// 输出 debug 信息console.log("11 " (11));}Component.onCompleted: {myFunction();} }结果: 2. real&…

PHP数组定义和输出

数组就是一组数据的集合,把一系列数据组织起来,形成一个可操作的整体。 PHP中的数组与Java的数组不一样,需要有key(键)和value(值),相当于Java中数组和键值对的结合。 数组的定义 …

zynqmp Linux + 裸机 (A53-0 Linux,A53-1 2 3 裸机大数据量实时处理,R5-0 协议处理,R5-1 屏幕显示逻辑等)填坑笔记

fpga 和arm 采用预留内存的方式,采用neon 协处理器只能做到 250M/S 的速度,预留内存采用mmap的方式,当读取内存页的时候采用缺页中断的方式,导致速度拖沓而且预留内存没有进行Linux系统的内存管理(在系统内 memcpy的速…

JMeter常见错误分析

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

《PySpark大数据分析实战》-17.云服务模式Databricks介绍运行作业

📋 博主简介 💖 作者简介:大家好,我是wux_labs。😜 热衷于各种主流技术,热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员(PCTA)、TiDB数据库专家(PCTP…

数据结构之进阶二叉树(二叉搜索树和AVL树、红黑树的实现)超详细解析,附实操图和搜索二叉树的实现过程图

绪论​ “生命有如铁砧,愈被敲打,愈能发出火花。——伽利略”;本章主要是数据结构 二叉树的进阶知识,若之前没学过二叉树建议看看这篇文章一篇掌握二叉树,本章的知识从浅到深的对搜索二叉树的使用进行了介绍和对其底层…

【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推荐--…

110基于matlab的混合方法组合的极限学习机和稀疏表示进行分类

基于matlab的混合方法组合的极限学习机和稀疏表示进行分类。通过将极限学习机(ELM)和稀疏表示(SRC)结合到统一框架中,混合分类器具有快速测试(ELM的优点)的优点,且显示出显着的分类精…

网安面试三十道题(持续更新)(sql注入系列)

61 给你一个网站,一般怎么做渗透测试的 先确定黑盒测试还是白盒测试 黑盒测试 信息收集: 服务器相关---:系统版本,真实IP,开放端口,使用的中间件 指纹信息---有无cdn加速,dns解析记录&#xff0…

ARM GIC(三) gicv2架构

ARM的cpu,特别是cortex-A系列的CPU,目前都是多core的cpu,因此对于多core的cpu的中断管理,就不能像单core那样简单去管理,由此arm定义了GICv2架构,来支持多核cpu的中断管理 一、gicv2架构 GICv2,支持最大8个core。其框图如下图所示: 在gicv2中,gic由两个大模块组成: …

页面级UI状态存储LocalStorage

目录 1、LocalStorageProp 2、LocalStorageLink 3、LocalStorage的使用 4、从UI内部使用LocalStorage 5、LocalStorageProp和LocalStorage单向同步的简单场景 6、LocalStorageLink和LocalStorage双向同步的简单场景 7、兄弟节点之间同步状态变量 LocalStorage是页面级的…

FISCO BCOS 中webase-deploy配置项详细说明

本文整理了webase-deploy的相关配置,例如如何webase启用基于自己搭的链,而不启用默认的两节点链 1.WeBASE 子系统版本 指定了 WeBASE 的各个子系统(web、mgr、sign、front)的版本号为 v1.5.5。 2.Docker 相关配置: docker.mysql 3.如果使用 Docker 安装&…

重温经典struts1之国际化(I18N)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 拿Google网站来举例,在世界上不同国家和地区,登陆Google网站,网站上都会显示本国家语言,它是怎么做到的,就是…

FasterRCNN目标检测

R-CNN 四个步骤: 对输入图片提取候选区(region proposal),每张大约2000个。论文中采用selective search的方法。对每个候选区采用CNN网络提取特征。此处需要将proposal的尺寸缩放成统一的227x227,以匹配CNN网络。最终提取到的特征…