设计模式之依赖倒转原则
目录
1、 基本介绍
2、 应用实例
3、 依赖关系传递的三种方式
(1) 接口传递
(2) 构造方法传递
(3) setter方式传递
4、 注意事项和细节
1、 基本介绍
依赖倒转原则(Dependence Inversion Principle)是指:
高层模块不应该依赖低层模块,二者都应该依赖其抽象(抽象类/接口),不要去依赖一个具体的子类
抽象不应该依赖细节,细节应该依赖抽象(这样稳定性会比较好)
依赖倒转(倒置)的中心思想是面向接口编程
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成(接口和抽象类的价值在于设计)
2、 应用实例
编程完成Person接收消息的功能。
(1) 传统方式
package com.principle.inversion;
public class DependecyInversion1 {public static void main(String[] args) {Person person = new Person();person.receive(new Email());}
}class Email{public String getInfo() {return "电子邮件信息:hello world";}
}
//方式一分析
//1.优点:简单,容易想到,容易实现
//2.缺点:如果我们获取的对象是 微信、短信等等,则需要新增类,同时Person也需要增加相应的接收方法(扩展性不好)
//3.解决思路:引入一个抽象的接口IReceiver,表示接收者,这样Person类与接口IReceiver发生依赖
// 因为Email,WeiXin等等都属于接收的范畴,它们各自实现IReceiver接口就可以了,这样就符合了依赖倒转原则class Person{public void receive(Email email) {System.out.println(email.getInfo());}
}
(2) 改进方式
package com.principle.inversion;
public class DependecyInversion1Improve {public static void main(String[] args) {//客户端无需改变Person person = new Person();person.receive(new Email());person.receive(new WeChat());}
}interface IReceiver{public String getInfo();
}class Email implements IReceiver{public String getInfo() {return "电子邮件信息:hello world";}
}class WeChat implements IReceiver{public String getInfo() {return "微信消息:hello";}
}class Person{public void receive(IReceiver receiver) {System.out.println(receiver.getInfo());}
}
3、 依赖关系传递的三种方式
(1) 接口传递
public class DependencyPass {public static void main(String[] args) {ChangHong changHong = new ChangHong();OpenAndClose openAndClose = new OpenAndClose();openAndClose.open(changHong);}
}// 方式 1: 通过接口传递实现依赖
// 开关的接口
interface IOpenAndClose {public void open(ITV tv); // 抽象方法,接收接口
}interface ITV { // ITV 接口public void play();
}class ChangHong implements ITV {@Overridepublic void play() {System.out.println("长虹电视机,打开");}
}
// 实现接口
class OpenAndClose implements IOpenAndClose {public void open(ITV tv) {tv.play();}
}
(2) 构造方法传递
public class DependencyPass {public static void main(String[] args) {ChangHong changHong = new ChangHong();//通过构造器进行依赖传递OpenAndClose openAndClose = new OpenAndClose(changHong);openAndClose.open();}
}
// 方式 2: 通过构造方法依赖传递
interface IOpenAndClose {public void open(); // 抽象方法
}interface ITV { // ITV 接口public void play();
}class OpenAndClose implements IOpenAndClose {public ITV tv; // 成员public OpenAndClose(ITV tv) { // 通过构造器将接口传入this.tv = tv;}public void open() { this.tv.play(); }
}class ChangHong implements ITV {@Overridepublic void play() {System.out.println("长虹电视机,打开");}
}
(3) setter方式传递
public class DependencyPass {public static void main(String[] args) {ChangHong changHong = new ChangHong();//通过 setter 方法进行依赖传递OpenAndClose openAndClose = new OpenAndClose();openAndClose.setTv(changHong);openAndClose.open();//没有setTv()直接open()就会报空指针异常}
}
// 方式 3 , 通过 setter 方法传递
interface IOpenAndClose {public void open(); // 抽象方法public void setTv(ITV tv);
}interface ITV { // ITV 接口public void play();
}class OpenAndClose implements IOpenAndClose {private ITV tv;public void setTv(ITV tv) { this.tv = tv; }public void open() { this.tv.play(); }
}class ChangHong implements ITV {@Overridepublic void play() {System.out.println("长虹电视机,打开");}
}
4、 注意事项和细节
(1)低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好.
(2)变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
比如:class A extends B{},其中B是一个抽象类/接口,在使用时:B obj = new A(),如果A类要进行扩展,只需要在B中增加一个方法即可。
(3)继承时遵循里氏替换原则
相关文章:
设计模式之依赖倒转原则
目录 1、 基本介绍 2、 应用实例 3、 依赖关系传递的三种方式 (1) 接口传递 (2) 构造方法传递 (3) setter方式传递 4、 注意事项和细节 1、 基本介绍 依赖倒转原则(Dependence Inversion Principle)是指: 高层模块不应该依赖低层模块,二者都应该依…...
Springboot启动后想要做某些事可以通过什么方法实现?
在Spring Boot应用中,如果你想在应用启动完成后执行一些特定的操作(例如缓存预热),可以实现CommandLineRunner或ApplicationRunner接口。这两个接口都提供了一个run方法,在Spring Boot应用上下文初始化完成后会被自动调…...
网络原理初识(2)
目录 一、协议分层 1、分层的作用 2、OSI七层模型 3、TCP / IP五层(或四层)模型 4、网络设备所在分层 5、网络分层对应 二、封装和分用 发送过程(封装) 1、应用层(应用程序) QQ 2、传输层 3、网络层 4、数据链路层 5、物理…...
【C++】每日一题 92 反转链表
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left < right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 class ListNode { public:int val;ListNode* next;ListNode(int _val) {val _val;next nullptr;} };…...
算法D39 | 动态规划2 | 62.不同路径 63. 不同路径 II
今天开始逐渐有 dp的感觉了,题目不多,就两个 不同路径,可以好好研究一下 62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。 代码随想录 视频讲解:动态规划中如何初始化很重要&#x…...
面试官:如何在 Spring Boot 启动的时候提前运行一些特定的代码
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:如何在 Spring Boot 启动的时候提前运行一些特定的代码 在Spring Boot启动的时候提前运行一些特定的代码可以通过实现ApplicationRunner接口、Com…...
力扣最热100题——56.合并区间
吾日三省吾身 还记得梦想吗 正在努力实现它吗 可以坚持下去吗 目录 吾日三省吾身 力扣题号:56. 合并区间 - 力扣(LeetCode) 题目描述 Java解法一:排序然后原地操作 具体代码如下 Java解法二:new一个list…...
docker学习(十四)docker搭建私服
docker私服搭建,配置域名访问,设置访问密码 启动registry docker run -d \-p 5000:5000 \-v /opt/data/registry:/var/lib/registry \registrydocker pull hello-world docker tag hello-world 127.0.0.1:5000/hello-world docker push 127.0.0.1:5000…...
基于BERTopic模型的英文20新闻数据集主题聚类及可视化
文章目录 bertopic介绍20 newsgroups dataset20 newsgroups数据集下载数据导入nltk数据处理bertopic模型构建模型训练运行模型可视化目前主题的一致性得分语料库建模bertopic介绍 BERTopic 是基于深度学习的一种主题建模方法。BERT 是一种用于 NLP 的预训练策略,它成功地利用…...
【Oracle之DataGuard的初步学习】
** 以下所有均是基于11G版本的 ** 一、DataGuard的部署方式 DG的部署最常用的方式就是直接在备库端部署一个空库然后再设置参数,但是这样做在初始同步时如果数据量过大会耗费较长的时间;相对来说这中方式比较简单不易出错。 还有一种方式就是通过rman的备…...
PyCharm无代码提示解决
PyCharm无代码提示解决方法 在使用PyCharm工具时,调用方法却无法进行提示,针对PyCharm无代码提示整理下解决方案 1、Python内置语法无智能提示 复现:我这里以urllib库读取网页内容为例,在通过urlopen()之后调用getur…...
记一次 .NET某设备监控自动化系统 CPU爆高分析
一:背景 1. 讲故事 先说一下题外话,一个监控别人系统运行状态的程序,结果自己出问题了,有时候想一想还是挺讽刺的,哈哈,开个玩笑,我们回到正题,前些天有位朋友找到我,说…...
大数据与云计算
目录 一、大数据时代二、云计算——大数据的计算三、云计算发展现状四、云计算实现机制五、云计算压倒性的成本优势 一、大数据时代 我们先来看看百度关于 “大数据”(Big Data)的搜索指数。 可以看出,“大数据” 这个词是从2012年才引起关注…...
一. 并行处理与GPU体系架构-并行处理简介
目录 前言0. 简述1. 串行处理与并行处理的区别2. 并行执行3. 容易混淆的几个概念4. 常见的并行处理总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习下课程第一章——并行处…...
vb机试考试成绩分析与统计,设计与实现(高数概率统计)-141-(代码+程序说明)
转载地址http://www.3q2008.com/soft/search.asp?keyword141 前言: 为何口出狂言,作任何VB和ASP的系统, 这个就是很好的一个证明 :) 又有些狂了... 数据库操作谁都会,接触的多了也没什么难的,VB编程难在哪?算法上,这个是一个算法题的毕业设计,里面涉及到对试卷的 平均分,最…...
Arm MMU深度解读
文章目录 一、MMU概念介绍二、虚拟地址空间和物理地址空间2.1、(虚拟/物理)地址空间的范围2.2、物理地址空间有效位(范围) 三、Translation regimes四、地址翻译/几级页表?4.1、思考:页表到底有几级?4.2、以4KB granule为例,页表的…...
2024 年 AI 辅助研发趋势
在2024年,AI辅助研发的应用趋势将非常广泛。举个例子,比如在医疗健康领域,AI将深度参与新药研发、早期癌症研究以及辅助诊断等,助力医疗技术的突破。同时,在农业领域,AI也将通过无人机、智能装备等方式&…...
聊聊pytho中的函数
Python中的函数 一、Python中函数的作用与使用步骤 1、为什么需要函数 在Python实际开发中,我们使用函数的目的只有一个“让我们的代码可以被重复使用” 函数的作用有两个: ① 代码重用(代码重复使用) ② 模块化编程&#x…...
Python中starmap有什么用的?
目录 前言 starmap函数的作用 starmap函数的用法 starmap函数的示例 1. 对每个元组元素进行求和 2. 对每个元组元素进行乘积 实际应用场景 1. 批量处理函数参数 2. 并行处理任务 3. 批量更新数据库 总结 前言 在Python中, starmap 是一个非常有用的函数&…...
面向切面编程 AOP
提示:主要内容参考动力节点老杜的Spring6讲义。 面向切面编程 AOP 一、AOP介绍二、AOP的七大术语三、切点表达式 IoC使软件组件松耦合。AOP让你能够捕捉系统中经常使用的功能,把它转化成组件。AOP(Aspect Oriented Programming)&a…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
