小谈设计模式(6)—依赖倒转原则
小谈设计模式(6)—依赖倒转原则
- 专栏介绍
- 专栏地址
- 专栏介绍
- 依赖倒转原则
- 核心思想
- 关键点分析
- a
- b
- c
- 优缺点分析
- 优点
- 降低模块间的耦合度
- 提高代码的可扩展性
- 便于进行单元测试
- 缺点
- 增加代码的复杂性
- 需要额外的设计和开发工作
- Java代码实现
- 示例分析
- 总结
专栏介绍
专栏地址
link
专栏介绍
主要对目前市面上常见的23种设计模式进行逐一分析和总结,希望有兴趣的小伙伴们可以看一下,会持续更新的。希望各位可以监督我,我们一起学习进步,加油,各位。
依赖倒转原则
依赖倒转原则(Dependency Inversion Principle,DIP)是面向对象设计中的一个重要原则,它指导着如何构建松耦合、可扩展和可维护的软件系统。该原则由罗伯特·C·马丁(Robert C. Martin)提出。
核心思想
通过抽象来解耦高层模块和低层模块之间的依赖关系。
关键点分析
a
高层模块不应该依赖于低层模块的具体实现,而是依赖于抽象接口。这意味着高层模块应该定义一个抽象接口,而低层模块实现该接口。通过依赖于抽象接口,高层模块可以独立于具体实现进行编程。
b
抽象接口应该由高层模块定义,而不是由低层模块定义。这样可以确保高层模块对于依赖的控制,而不会受到低层模块的限制。高层模块可以根据自己的需求定义接口的方法和属性,而不需要依赖于低层模块的具体实现细节。
c
依赖注入是实现依赖倒转原则的重要手段。通过依赖注入,高层模块可以将具体实现类的对象传递给抽象接口。依赖注入可以通过构造函数、方法参数或者属性注入的方式实现。这样可以实现解耦,高层模块不需要关心具体实现类的创建和管理。
优缺点分析
优点
降低模块间的耦合度
通过依赖倒转原则,高层模块不依赖于低层模块的具体实现,而是依赖于抽象接口。这样可以使得模块之间的耦合度降低,提高代码的灵活性和可维护性。
提高代码的可扩展性
由于高层模块不依赖于低层模块的具体实现,当需要新增或修改低层模块时,只需要修改具体实现类而不需要修改高层模块的代码。这样可以提高代码的可扩展性,减少对现有代码的影响。
便于进行单元测试
由于高层模块依赖于抽象接口,可以通过使用模拟对象来进行单元测试,而不需要依赖于具体实现类。这样可以更容易地进行测试,提高代码的质量。
缺点
增加代码的复杂性
依赖倒转原则需要引入抽象接口和依赖注入等机制,这会增加代码的复杂性和理解难度。特别是在项目规模较小或简单场景下,引入这些机制可能会显得过于繁琐。
需要额外的设计和开发工作
在应用依赖倒转原则时,需要进行额外的设计和开发工作,包括定义抽象接口、实现具体实现类、进行依赖注入等。这会增加开发成本和工作量。
综上所述,依赖倒转原则在一定程度上可以提高代码的灵活性、可维护性和可扩展性,但也需要权衡其引入的复杂性和开发成本。在设计和开发过程中,需要根据具体的场景和需求来决定是否采用依赖倒转原则。
Java代码实现
// 定义抽象接口
public interface MessageSender {void sendMessage(String message);
}// 具体实现类1
public class EmailSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("Sending email: " + message);}
}// 具体实现类2
public class SmsSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("Sending SMS: " + message);}
}// 高层模块,依赖于抽象接口
public class NotificationService {private MessageSender messageSender;// 通过构造函数进行依赖注入public NotificationService(MessageSender messageSender) {this.messageSender = messageSender;}public void sendNotification(String message) {// 调用抽象接口的方法messageSender.sendMessage(message);}
}// 测试代码
public class Main {public static void main(String[] args) {// 创建具体实现类的对象MessageSender emailSender = new EmailSender();MessageSender smsSender = new SmsSender();// 创建高层模块的对象,并传入具体实现类的对象NotificationService emailNotificationService = new NotificationService(emailSender);NotificationService smsNotificationService = new NotificationService(smsSender);// 调用高层模块的方法emailNotificationService.sendNotification("Hello, this is an email notification.");smsNotificationService.sendNotification("Hello, this is an SMS notification.");}
}
示例分析
在抽象接口MessageSender定义了发送消息的方法。具体实现类EmailSender和SmsSender分别实现了该接口,并提供了发送邮件和发送短信的具体实现。高层模块NotificationService依赖于抽象接口MessageSender,通过构造函数进行依赖注入,从而实现了依赖倒转原则。
总结
依赖倒置原则强调了面向抽象编程的重要性,通过抽象接口和依赖注入等技术,可以降低模块之间的耦合度,提高代码的灵活性和可维护性。
相关文章:

小谈设计模式(6)—依赖倒转原则
小谈设计模式(6)—依赖倒转原则 专栏介绍专栏地址专栏介绍 依赖倒转原则核心思想关键点分析abc 优缺点分析优点降低模块间的耦合度提高代码的可扩展性便于进行单元测试 缺点增加代码的复杂性需要额外的设计和开发工作 Java代码实现示例分析 总结 专栏介绍…...

JetBrains常用插件
Codota AI Autocomplete Java and JavaScript:自动补全插件 Background Image plus:背景图片设置 rainbow brackets:彩虹括号,便于识别 CodeGlance2: 类似于 Sublime 中的代码缩略图(代码小地图ÿ…...

【C++哈希应用】位图、布隆过滤器
【C哈希应用】位图、布隆过滤器 目录 【C哈希应用】位图、布隆过滤器位图概念位图的实现位图改造位图应用总结布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的查找布隆过滤器删除布隆过滤器优点布隆过滤器缺陷 作者:爱写代码的刚子 时间:2023.9…...
Qt 编译纯c的C99的项目, error: undefined reference to `f()‘
把Cpp的后缀该为C是什么样的 尝试引用一个奇门排盘的c程序,在git上找到的叫cqm, 然后总是报错 error: undefined reference to f() 很是郁闷 于是新建了个项目试验一下,终于摸清了需要命名空间。 后来这么写就可以了 a.h namespace XX …...

TensorFlow入门(五、指定GPU运算)
一般情况下,下载的TensorFlow版本如果是GPU版本,在运行过程中TensorFlow能自动检测。如果检测到GPU,TensorFlow会默认利用找到的第一个GPU来执行操作。如果机器上有超过一个可用的GPU,除第一个之外的其他GPU默认是不参与计算的。如果想让TensorFlow使用这些GPU执行操作,需要将运…...

Unity - 实践: Metallic流程贴图 转 Specular流程贴图
文章目录 目的Metallic Flow - SP - 输出输出的 MRA (MGA) 贴图 Metallic->Specular (根据教程一步一步实践)1. Base color Metallic -> Diffuse2. Base color Metallic -> Specular3. Roughness -> Glossiness输出贴图,在 unity 中展示:M…...
第三章:最新版零基础学习 PYTHON 教程(第四节 - Python 运算符—Python 逻辑运算符及示例)
运算符用于对值和变量执行操作。这些是执行算术和逻辑计算的特殊符号。运算符运算的值称为操作数。 表中的内容逻辑运算符 逻辑与运算符 逻辑或运算符 逻辑非运算符 逻辑运算符的求值顺序 逻辑运算符 在 Python 中,逻辑运算符用于条件语句(True 或 False)。它们执行逻辑 AN…...
如何做好测试?(三)功能测试 (Functional Testing, FT)
1. 功能测试的详细介绍: 功能测试 (Functional Testing, FT),是一种软件测试方法,旨在验证系统的功能是否按照需求规格说明书或用户期望的方式正常工作。它关注系统的整体行为,以确保各个功能模块和组件之间的交互和集成正确。 …...
Ubuntu-Server-22.04安装桌面+VNC
前提:Ubuntu Server安装好后,ubantu其他版本是否适用这里未知,欢迎大佬们前来评论 一、默认没有图形界面,有时觉得用图形界面操作更简单直接,于是用如下命令安装: 1.更新本地环境 sudo apt-get update s…...

职业规划,什么是职业兴趣 - 我喜欢做什么?
能够在工作岗位上面做出成绩的人,都是结合自身兴趣,对职业进行合理规划的那一类。尤其是步入中年以后,能够创造出巨大价值的人,无一例外都是喜欢自己职业的人。没有将兴趣融入工作的人,只能够忍受默默无闻地活着&#…...

基于Java的高校学生党员发展流程管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...

【NLP的python库(03/4) 】: 全面概述
一、说明 Python 对自然语言处理库有丰富的支持。从文本处理、标记化文本并确定其引理开始,到句法分析、解析文本并分配句法角色,再到语义处理,例如识别命名实体、情感分析和文档分类,一切都由至少一个库提供。那么,你…...
面试理论篇三
关于异常机制篇 异常描述 目录 关于异常机制篇异常描述 注:自用 1,Java中的异常分为哪几类?各自的特点是什么? Java中的异常 可以分为 可查异常(Checked Exception)、运行时异常(Runtime Exception) 和 错误(Error)三类。可查异…...
ShardingSphere|shardingJDBC - 在使用数据分片功能情况下无法配置读写分离
问题场景: 最近在学习ShardingSphere,跟着教程一步步做shardingJDBC,但是想在开启数据分片的时候还能使用读写分离,一直失败,开始是一直能读写分离,但是分偏见规则感觉不生效,一直好像是走不进去…...
char s1[len + 1]; 报错说需要常量?
在C中,字符数组的大小必须是常量表达式,不能使用变量 len 作为数组大小。为了解决这个问题,你可以使用 new 运算符动态分配字符数组的内存,但在使用完后需要手动释放。 还有啥是只能这样的,还是说所有的动态都需要new&…...

【Linux】CentOS-6.8超详细安装教程
文章目录 1.CentOS介绍:2.必要准备:3.创建虚拟机:4 .安装系统 1.CentOS介绍: CentOS是一种基于开放源代码的Linux操作系统,它以其稳定性、安全性和可靠性而闻名,它有以下特点: 开源性࿱…...

【Java 进阶篇】MySQL启动与关闭、目录结构以及 SQL 相关概念
MySQL 服务启动与关闭 MySQL是一个常用的关系型数据库管理系统,通过启动和关闭MySQL服务,可以控制数据库的运行状态。本节将介绍如何在Windows和Linux系统上启动和关闭MySQL服务。 在Windows上启动和关闭MySQL服务 启动MySQL服务 在Windows上&#x…...
Android 11.0 mt6771新增分区功能实现一
1.前言 在11.0的系统开发中,在对某些特殊模块中关于数据的存储方面等需要新增分区来保存, 所以就需要在系统分区新增分区,接下来就来实现这个功能 2.mt6771新增分区功能实现一的核心类 build/make/core/Makefile build/make/core/board_config.mk build/make/core/config…...
LiveData简单使用
1.LiveData是基于观察者模式,可以用于处理消息的订阅分发的组件。 LiveData组件有以下特性: 1) 可以感知Activity、Fragment生命周期变化,因为他把自己注册成LifecycleObserver。 2) LiveData可以注册多个观察者,只有数据…...

手动实现Transformer
Transformer和BERT可谓是LLM的基础模型,彻底搞懂极其必要。Transformer最初设想是作为文本翻译模型使用的,而BERT模型构建使用了Transformer的部分组件,如果理解了Transformer,则能很轻松地理解BERT。 一.Transformer模型架构 1…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...