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

2023-12-23 10:44

本文主要是介绍深入理解依赖反转原则(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层的东西吗?不需要!依赖反转原则应该作为大家在做架构设计时重要规则

这篇关于深入理解依赖反转原则(DIP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/527749

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

每天认识几个maven依赖(ActiveMQ+activemq-jaxb+activesoap+activespace+adarwin)

八、ActiveMQ 1、是什么? ActiveMQ 是一个开源的消息中间件(Message Broker),由 Apache 软件基金会开发和维护。它实现了 Java 消息服务(Java Message Service, JMS)规范,并支持多种消息传递协议,包括 AMQP、MQTT 和 OpenWire 等。 2、有什么用? 可靠性:ActiveMQ 提供了消息持久性和事务支持,确保消

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分