设计模式之依赖倒转原则

news2025/2/25 13:32:07

在软件开发的世界里,设计模式一直是提升代码质量、确保软件稳定性以及优化软件可维护性的重要工具。而在这其中,依赖倒转原则无疑是其中最具代表性的设计模式之一。那么,什么是依赖倒转原则?它又为何如此重要?让我们一起来探讨。

一、依赖倒转原则的定义

依赖倒转原则是面向对象设计的基本原则之一,它的核心思想是:依赖于抽象,不依赖于具体。简单来说,就是将代码的依赖关系从具体类转向抽象类或者接口,降低类之间的耦合度,增强代码的灵活性和可扩展性。

二、如何实现依赖倒转原则
1️⃣使用抽象类或接口

抽象类和接口是实现依赖倒转原则的关键。通过定义抽象类或接口,我们可以规定一组通用的方法或属性,然后由具体的子类来实现这些方法或属性。

2️⃣合理使用依赖注入

依赖注入是一种实现依赖倒转原则的重要手段。通过将依赖关系注入到对象中,我们可以降低对象之间的耦合度,使得代码更加灵活和可扩展。

3️⃣遵循里氏替换原则

里氏替换原则是依赖倒转原则的一个重要补充。它的核心思想是:子类型必须能够替换其父类型而不会引发任何错误或异常。这要求子类必须实现父类所定义的所有方法,并且不能添加新的属性或方法。

三、依赖倒转原则在实践中的应用

假设有一个EmailService类,它直接依赖于SMTPServer类来发送电子邮件。

SMTPServer类
class SMTPServer {
    void sendEmail(String email) {
        // 实现发送邮件的具体逻辑
    }
}
 EmailService类
class EmailService {
    private SMTPServer smtpServer;

    EmailService() {
        this.smtpServer = new SMTPServer();
    }

    void sendNotification(String email) {
        smtpServer.sendEmail(email);
    }
}

在这个例子中,EmailService依赖于具体的SMTPServer实现,违反了依赖倒转原则。当需要更换邮件服务提供商时,比如改为使用MailgunAPI服务,就需要修改EmailService的构造函数和内部实现。

程序调整

为遵循依赖倒转原则,我们可以引入一个抽象接口EmailSender,让EmailService依赖于这个抽象接口而非具体的邮件发送实现。

EmailSender 接口
interface EmailSender {
    void sendEmail(String email);
}
调整后SMTPServer类 
class SMTPServer implements EmailSender {
    @Override
    void sendEmail(String email) {
        // 实现发送邮件的具体逻辑
    }
}
MailgunAPI 类
class MailgunAPI implements EmailSender {
    @Override
    void sendEmail(String email) {
        // 使用Mailgun API实现发送邮件逻辑
    }
}
调整后EmailService类
class EmailService {
    private EmailSender emailSender;

    EmailService(EmailSender emailSender) {
        this.emailSender = emailSender;
    }

    void sendNotification(String email) {
        emailSender.sendEmail(email);
    }
}

现在,EmailService依赖于抽象的EmailSender接口,具体邮件发送的方式可以通过构造函数注入不同的实现类,这就遵循了依赖倒转原则。当需要切换邮件服务提供商时,只需要更换传递给EmailService的EmailSender实例即可,无需修改EmailService的内部实现。

四、总结

依赖倒转原则是面向对象设计的重要原则之一,它能够显著提高代码的质量和可维护性。通过合理地使用抽象类、接口和依赖注入等技术手段,我们可以打破传统的设计思维模式,让代码更加自由和灵活。在未来的软件开发中,我们应当更加重视依赖倒转原则的应用,从而不断提升我们的编程技能和软件质量。

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

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

相关文章

鼎捷软件获评国家级智能制造“AAA级集成实施+AA级咨询设计”供应商

为贯彻落实《“十四五”智能制造发展规划》,健全智能制造系统解决方案供应商(以下简称“供应商”)分类分级体系,推动供应商规范有序发展,智能制造系统解决方案供应商联盟组织开展了供应商分类分级评定(第一批)工作,旨在遴选一批专…

Python--GIL(全局解释器锁)

在Python中,GIL(全局解释器锁)是一个非常重要的概念,它对Python的多线程编程有着深远的影响。GIL是Python解释器级别的锁,用于保证任何时刻只有一个线程在执行Python字节码。这意味着即使在多核处理器上,Py…

[HTML]Web前端开发技术13(HTML5、CSS3、JavaScript )横向二级导航菜单 Web页面设计实例——喵喵画网页

希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的…

离线数据仓库-关于增量和全量

数据同步策略 数据仓库同步策略概述一、数据的全量同步二、数据的增量同步三、数据同步策略的选择 数据仓库同步策略概述 应用系统所产生的业务数据是数据仓库的重要数据来源,我们需要每日定时从业务数据库中抽取数据,传输到数据仓库中,之后…

探索Redis特殊数据结构:Bitmaps(位图)在实际中的应用

一、概述 Redis官方提供了多种数据类型,除了常见的String、Hash、List、Set、zSet之外,还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic(HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Confi…

一文掌握SpringBoot注解之@Async知识文集(1)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

手把手教你搭建一个数据可视化看板

前言 俗话说的好,“字不如表,表不如图”、“有图有真相,一图胜千言”。 数据可视化就是用图的形式把基础数据直观,简洁的,高效的展示出来,今天为大家介绍一下如何使用葡萄城公司的嵌入式BI工具——Wyn商业…

Unity3d C#实现场景编辑/运行模式下3D模型XYZ轴混合一键排序功能(含源码工程)

前言 在部分场景搭建中需要整齐摆放一些物品(如仓库中的货堆、货架等),因为有交互的操作在单个模型上,每次总是手动拖动模型操作起来也是繁琐和劳累。 在这背景下,我编写了一个在运行或者编辑状态下都可以进行一键排序…

Day12 C基础(指针进阶)

文章目录 指针修饰1.const 修饰2.void 大小端二级指针指针和数组1.指针和一维数组直接访问:间接访问: 2.指针和二维数组直接访问:间接访问: 数组指针 指针修饰 1.const 修饰 1)const int num 10; const int num 10;num 3; i…

【面试合集】说说微信小程序的实现原理?

面试官:说说微信小程序的实现原理? 一、背景 网页开发,渲染线程和脚本是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应的原因,本质就是我们常说的 JS 是单线程的 而在小程序中,选择了 H…

Mac系统下,保姆级Jenkins自动化部署Android

一、Jenkins自动化部署 1、安装jenkins 官网:macOS Installers for Jenkins LTS 选择macOS brew install jenkins-lts 安装最新: brew install jenkins-lts 启动jenkins服务: brew services start jenkins-lts 重启jenkins服务: brew services restart jenkin…

YOLOv5改进系列(27)——添加SCConv注意力卷积(CVPR 2023|即插即用的高效卷积模块)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2)——添加CBAM注意力机制 YOLOv5改进系列&…

Netty-Netty源码分析

Netty线程模型图 Netty线程模型源码剖析图 Netty高并发高性能架构设计精髓 主从Reactor线程模型NIO多路复用非阻塞无锁串行化设计思想支持高性能序列化协议零拷贝(直接内存的使用)ByteBuf内存池设计灵活的TCP参数配置能力并发优化 无锁串行化设计思想 在大多数场景下&#…

如何用GPT进行论文润色与改写?

详情点击链接:如何用GPT/GPT4进行论文润色与改写?一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析,AI画图,图像识别,文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二…

1.16 day3 IO网络编程

用udp实现tftp下载功能 #include <myhead.h> #define PORT 69 #define IP "192.168.122.24" int xiazai(int sfd,struct sockaddr_in sin,int fd,socklen_t socklen) {char buf[516]"";char ack[4];short *p1(short *)buf;*p1htons(1);char *p2buf2…

数字化转型:为何失败率居高不下,以及如何避免重蹈覆辙

在当今快速发展的数字化时代&#xff0c;许多企业纷纷投身于数字化转型的浪潮中&#xff0c;以期通过技术革新提升竞争力、优化运营、提高效率。然而&#xff0c;尽管数字化转型的潜在益处巨大&#xff0c;但失败率却居高不下&#xff0c;甚至导致企业陷入困境。 本文将深入探讨…

Git版本控制——分支

分支 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着可以把工作从开发主线上分离开来进行重大的Bug修改、开发新的功能&#xff0c;以免影响开发主线。 查看本地分支 git branch创建本地分支 git branch 分支名切换分支(checkout) git checkout 分支名创建…

jenkins url发生改变如何修改回来

问题&#xff1a; 我的jenkins服务器部署完后&#xff0c;此时url就已经固定了如下&#xff1a; 但是我更换了公网IP&#xff0c;url地址还是旧的&#xff0c;现在就需要修改一下配置文件&#xff1b; 修改配置文件 ($JENKINS_HOME/jenkins.model.JenkinsLocationConfiguratio…

java日志框架总结

一、日志框架简单分类介绍 java常用的日志框架、可以分为两组&#xff1a; 1、JCL、JUL、Log4j&#xff1b; 2、SLF4J、Log4j2、Logback&#xff1b; 其中第一组是比较早期的日志实现框架&#xff0c;JCL并不是具体的日志实现框架&#xff0c;JCL其实是定义了一…

SparkSQL——Dataset

Dataset Dataset 是什么&#xff1f; Testdef dataset1():Unit {// 1. 创建 SparkSessionval spark new SparkSession.Builder().master("local[6]").appName("dataset1").getOrCreate()// 2. 导入隐式转换import spark.implicits._// 3. 演示val sourceR…