Java设计模式之依赖倒置原则使用举例说明

示例1:司机驾驶汽车

问题场景:司机类直接依赖奔驰车类,新增宝马车需修改司机类代码。

// 未遵循DIP
class Benz { public void run() { /*...*/ } }
class Driver { public void drive(Benz benz) { benz.run(); } 
}
// 遵循DIP:引入接口ICar
interface ICar { void run(); }
class Benz implements ICar { /*...*/ }
class BMW implements ICar { /*...*/ }
class Driver { public void drive(ICar car) { car.run(); } 
}

效果:新增汽车类型(如BMW)无需修改Driver类,仅需实现ICar接口。


示例2:用户接收消息

问题场景:用户类直接依赖邮件类,新增微信或短信需修改用户类。

// 未遵循DIP
class Email { public String getInfo() { /*...*/ } }
class Person { public void receive(Email email) { /*...*/ } 
}
// 遵循DIP:引入接口IReceiver
interface IReceiver { String getInfo(); }
class Email implements IReceiver { /*...*/ }
class WeChat implements IReceiver { /*...*/ }
class Person { public void receive(IReceiver receiver) { /*...*/ } 
}

效果:新增消息类型(如WeChat)无需修改Person类,仅需实现IReceiver接口。


示例3:购物场景

问题场景:顾客类直接依赖具体商品类(如汉堡、薯条),新增商品需修改顾客类。

// 未遵循DIP
class Hamburger { public void eat() { /*...*/ } }
class Person { public void buy(Hamburger hamburger) { hamburger.eat(); } 
}
// 遵循DIP:引入接口IDishes
interface IDishes { void eat(); }
class Hamburger implements IDishes { /*...*/ }
class Chips implements IDishes { /*...*/ }
class Person { public void buy(IDishes dishes) { dishes.eat(); } 
}

效果:新增商品类型(如Chips)无需修改Person类,仅需实现IDishes接口。


示例4:通知服务

问题场景:通知服务直接依赖邮件发送类,更换短信服务需修改通知逻辑。

// 未遵循DIP
class EmailService { public void sendEmail(String msg) { /*...*/ } }
class NotificationService { public void send(String msg) { new EmailService().sendEmail(msg); } 
}
// 遵循DIP:引入接口MessageSender
interface MessageSender { void sendMessage(String msg); }
class EmailService implements MessageSender { /*...*/ }
class SMSService implements MessageSender { /*...*/ }
class NotificationService { private MessageSender sender; public NotificationService(MessageSender sender) { this.sender = sender; } public void send(String msg) { sender.sendMessage(msg); } 
}

效果:通过构造器注入依赖,更换消息服务(如SMSService)仅需修改调用层。


依赖传递的三种方式

  1. 接口传递:通过方法参数传递抽象(如Driver.drive(ICar car))。
  2. 构造器注入:通过构造函数依赖注入(如NotificationService依赖MessageSender)。
  3. Setter注入:通过Setter方法动态注入依赖(如public void setSender(MessageSender sender))。

DIP的核心优势

  1. 降低耦合性:模块间通过抽象交互,减少直接依赖。
  2. 提高扩展性:新增功能只需添加实现类,无需修改高层逻辑(符合开闭原则)。
  3. 支持并行开发:接口定义后,高低层模块可独立开发与测试(如TDD模式)。
  4. 增强可维护性:变更影响范围受限于低层模块,减少风险。

总结

依赖倒置原则通过抽象(接口/抽象类)实现模块解耦,核心实践包括:

  • 定义清晰的接口或抽象类作为模块间的契约。
  • 使用依赖注入(构造器、Setter等)传递具体实现。
  • 高层模块仅依赖抽象,低层模块实现抽象。
    结合Spring框架的DI容器,可进一步自动化依赖管理,提升代码复用性和灵活性。

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

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

相关文章

【Docker】openEuler 使用docker-compose部署gitlab-ce

docker-compose配置 services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlab.example.comenvironment:GITLAB_OMNIBUS_CONFIG: |# Add any other gitlab.rb configuration here, each on its own lineexternal_url https://gi…

ElasticSearch 父子文档使用简记

一. ES parent-child 文档简介 ES 提供了类似数据库中 Join 联结的实现,可以通过 Join 类型的字段维护父子关系的数据,其父文档和子文档可以单独维护。 二. 父子文档的索引创建与数据插入 ES 父子文档的创建可以分为下面三步: 创建索引 M…

【Linux】编辑器vim的使用

目录 1. vim的基本概念 2. vim的基本使用 3. vim命令模式操作 3.1 移动光标 3.2 删除 3.3 复制 3.4 替换 3.5 撤销 3.6 更改 3.7 跳转 4. vim底行模式操作 4.1 列出行号 4.2 跳到文件中的某行 4.3 查找字符 4.4 保存文件 4.5 离开vim 1. vim的基本概念 Vim&…

《零基础掌握飞算Java AI:核心概念与案例解析》

前引:飞算科技是一家专注于企业级智能化技术服务的公司,核心领域包括AI、大数据、云计算等。其Java AI解决方案主要面向企业级应用开发,提供从数据处理到模型部署的全流程支持!飞算Java AI是一款基于人工智能技术的Java开发辅助工…

Chrome腾讯翻译插件transmart的安装

文章目录一、官网地址二、安装过程1. 下载插件2. 解压crx3, chrome安装三、如何使用一、官网地址 腾讯翻译插件官网 二、安装过程 1. 下载插件 点击上面的官网地址,下拉到如图所示chrome插件位置,点击立即下载 2. 解压crx 从压缩文件中解压出crx文…

IOMMU的2级地址翻译机制及多级(2~5)页表查找

IOMMU的2级地址翻译机制及多级(2~5)页表查找 摘要:IOMMU是现代计算机系统中用于I/O设备(如GPU、NIC、网络接口卡)的地址翻译和保护机制,类似于CPU的MMU(Memory Management Unit),但专为设备DMA(Direct Memory Access,直接内存访问)设计。它支持虚拟化环境(…

C++STL标准模板库详解

一、引言STL(Standard Template Library)是 C 标准库的核心组成部分,其中容器(Containers) 作为数据存储的基础组件,为开发者提供了丰富的数据结构选择。本文将聚焦 STL 容器的核心类型,结合具体…

神经网络 常见分类

📚 神经网络的常见分类方式可以从不同角度来划分,以下是几种主流思路,帮你快速梳理清晰:1️⃣ 按网络结构分类前馈神经网络(Feedforward Neural Network, FNN) 数据从输入层→隐藏层→输出层单向传递&#…

生产环境Redis缓存穿透与雪崩防护性能优化实战指南

生产环境Redis缓存穿透与雪崩防护性能优化实战指南 在当下高并发场景下,Redis 作为主流缓存组件,能够极大地提升读写性能,但同时也容易引发缓存穿透、缓存击穿及缓存雪崩等问题,导致后端依赖数据库的请求激增,系统稳定…

【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)

🔥个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C基础知识知识强化补充、C/C干货分享&学习过程记录 🍉学习方向:C/C方向 ⭐️人…

嵌入式硬件篇---常见的单片机型号

以下是目前常用的单片机型号及其应用场景、优劣势的详细解析,结合最新行业动态和技术特性,帮助你精准匹配需求:一、经典 8 位单片机:低成本入门首选1. 51 系列(代表型号:AT89C51、STC89C52)应用…

windows下ArcGIS 10.8.2下载安装教程

ArcGIS是由美国环境系统研究所(Esri)开发的一款功能强大且应用广泛的综合性地理信息系统(GIS)软件平台,在空间数据的采集、管理、分析、可视化和共享等方面表现出色,是GIS领域的标杆产品。它拥有丰富的功能…

防御保护15

混合密码体系 --- 数字信封 逻辑 --- 先用快速的对称密钥来对消息进行加密,保证数据的机密性。然后只需要保证对称密钥的机密性即可,使用公钥密钥体系来对对称秘钥消息进行加密。身份认证和数据认证技术 Hash散列 指纹 ---> 单向散列函数 Hash --->…

Linux上管理Java的JDK版本

1.alternatives简介alternatives是 Linux 系统(尤其是 ​​RHEL/CentOS/Fedora​​ 等基于 RPM 的发行版)中用于管理​​同一软件多个版本​​的系统工具。它通过维护符号链接(软链接)的层级结构,帮助用户在不冲突的情…

webrtc编译arm/arm64

webrtc版本 m125版本 编译arm sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf //下载失败,需要多次尝试 python3 build/linux/sysroot_scripts/install-sysroot.py --arch=arm //python3 bui

【读论文】医疗AI大模型:百川开源Baichuan-M2

1. 引言 最新百川开源了一个可以和openai新模型掰手腕的医疗垂直大模型:Baichuan-M2在HealthBench基准上取值60.1的高分,超过了gpt-oss-120b。这次一起回顾下百川给的技术报告。 2. Baichuan-M2概览:“模型+系统” Baichuan-M2的成功源于一套精心设计的、端到端的训练与优…

OBOO鸥柏丨75寸/86平板企业办公会议触控一体机核心国产化品牌招投标参数

OBOO鸥柏整机参数要求:55寸/65寸/75寸/85-86寸/98寸/100寸/110寸/115寸智能会议平板教学触控一体机/智慧黑板触摸屏参数要求。系统可灵活选择如:支持安卓(Android),Windows可选择。并在KylinOS银河麒麟操作系统、统信U…

DCT域信息隐藏中超参数影响的深度解析:从理论到实践的完整指南

摘要 随着数字媒体技术的飞速发展,信息隐藏技术在版权保护、内容认证和隐私保护等领域发挥着越来越重要的作用。离散余弦变换(DCT)域作为信息隐藏的经典载体,因其与JPEG压缩标准的天然兼容性而备受关注。然而,DCT域信息隐藏的效果很大程度上取决于各种超参数的精心调节,…

YOLOv8环境配置命令

【YOLOv8】一小时掌握,从0开始搭建部署YOLOv8系列教程,安装推理自定义数据集训练与搭建_哔哩哔哩_bilibili【YOLOv8】一小时掌握,从0开始搭建部署YOLOv8系列教程,安装推理自定义数据集训练与搭建共计10条视频,包括&…

Maven私服配置模版

参考课程: 【黑马程序员 JavaWeb开发教程】 [https://www.bilibili.com/video/BV1m84y1w7Tb] ZZHow(ZZHow1024)Maven 的 settings.xml 配置文件中(从私服下载项目到本地) 在 servers 标签中,配置访问私服的个人凭证(访问的用户名和…