设计模式之依赖倒转原则

news/2024/4/19 15:04:55/文章来源:https://blog.csdn.net/qq_63438013/article/details/136520629

目录

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)继承时遵循里氏替换原则

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

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

相关文章

【单调栈】Leetcode 739.每日温度

【单调栈】Leetcode 739.每日温度 解法:维护单调栈栈中存的是数组的索引 解法:维护单调栈栈中存的是数组的索引 栈中存的是数组的索引 当新的值比当前栈顶的大,那么就执行出栈-更新result数组-判断当新的值比当前栈顶的大?的循环…

如何学习I2C协议

文章目录 学习I2C协议0 懒人直达1 了解协议开发者2 从恩智浦半导体公司下载官方技术文档3 翻译成中文4 资源下载 学习I2C协议 0 懒人直达 点击直达 1 了解协议开发者 I2C(Inter-Integrated Circuit)协议是由荷兰皇家飞利浦电子公司(现恩智…

Unity Samples和帧动画的问题

拖动序列帧图片和自己创建clip的帧率不同 我今天在创建帧动画的时候用了两种方式第一种是直接拖动序列帧图片到Hierachy,然后生成的第二种是这样我发现两者播放的动画速率不一样最后查了半天查不到原因。最后发现是Samples的原因,而且Unity把Samples这个…

Python数据处理实战(4)-上万行log数据提取并作图进阶版

系列文章: 0、基本常用功能及其操作 1,20G文件,分类,放入不同文件,每个单独处理 2,数据的归类并处理 3,txt文件指定的数据处理并可视化作图 4,上万行log数据提取并作图进阶版&a…

外包干了5天,技术退步明显。。。。。

在湖南的一个安静角落,我,一个普通的大专生,开始了我的软件测试之旅。四年的外包生涯,让我在舒适区里逐渐失去了锐气,技术停滞不前,仿佛被时间遗忘。然而,生活的转机总是在不经意间降临。 与女…

别再盲目推广!用Xinstall精准追踪App下载渠道

在移动互联网时代,App推广已经成为企业获取用户、提升品牌知名度的重要手段。然而,面对众多的推广渠道和复杂的用户行为,如何精准统计App下载渠道来源,成为了广告主和开发者亟待解决的问题。今天,我们就来聊聊国内专业…

Go 互斥锁的实现原理?

Go sync包提供了两种锁类型:互斥锁sync.Mutex 和 读写互斥锁sync.RWMutex,都属于悲观锁。 概念 Mutex是互斥锁,当一个 goroutine 获得了锁后,其他 goroutine 不能获取锁(只能存在一个写者或读者,不能同时…

docker 部署prometheus+grafana

首先进行部署docker 配置阿里云依赖: curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo # 配置centos 7的镜像源 yum install -y yum-utils device-mapper-persistent-data lvm2 # 安装一些后期或需要的的一下依…

[Java 探索之路~大数据篇] 新时代大数据流处理入门指南

本文主要介绍大数据基础,以及 flink 流计算 文章目录 【基础知识】1. 批处理与流处理1.批处理2.流处理 2. 为什么需要一个优秀的流处理框架1. 股票交易的业务场景2.生产者——消费者模型3. 流处理框架要解决的诸多问题(1)可扩展性&#xff08…

2024年腾讯云学生服务器优惠活动「云+校园」政策解读

2024年腾讯云学生服务器优惠活动「云校园」,学生服务器优惠价格:轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年,轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年,CVM云服务器2核4G配置842.4元一年&…

【C++从0到王者】第五十一站:B+树

文章目录 一、B树1.B树的概念2.B树的特性3.B树的插入的过程4.总结 二、B*树1. B*树的概念2.B*树的分裂 三、总结四、B树系列和哈希和平衡搜索树作对比五、B树的一些应用1.索引2.MySQL索引3.MyISAM2.InnoDB 一、B树 1.B树的概念 B树是B树的变形,是在B树基础上优化的…

C++ 链表OJ

目录 1、2. 两数相加 2、24. 两两交换链表中的节点 3、143. 重排链表 4、23. 合并 K 个升序链表 5、25. K 个一组翻转链表 解决链表题目常用方法: 1、画图 2、引入虚拟"头”结点 便于处理边界情况方便我们对链表操作 3、大胆定义变量,减少连接…

2024-3-7 市场分歧视角

昨天安奈儿市场带领市场情绪一致,新型工业化方向独占鳌头,日内高潮节点尾盘老龙 克来机电涨停,昨晚很多老师在YY老龙是不是要二波了,呵呵。 今天市场分歧从竞价就开始了,隔夜单我记忆中 天奇股份88亿,上海…

python71-Python的函数入门,定义函数和调用函数

在使用函数之前必须先定义函数,定义函数的语法格式如下: def 函数名(形参列表)://由零条到多条可执行语句组成的函数[return [返回值]] Python声明函数必须使用def关键字,对函数语法格式的详细说明如下。 1)函数名:从语法角度来…

力扣--从前序与中序遍历序列构造二叉树

题目: 思想: 首先先序遍历能确定根节点的值,此时查看该值在中序遍历中的位置(如果索引为i),那么i左侧为左子树,i 右侧为右子树。从中序数组中即可看出左子树结点个数为 i,右子树节点…

Pytorch学习 day06(torchvision中的datasets、dataloader)

torchvision的datasets 使用torchvision提供的数据集API,比较方便,如果在pycharm中下载很慢,可以URL链接到迅雷中进行下载(有些URL链接在源码里)代码如下: import torchvision # 导入 torchvision 库 # …

线程池不香了? 结构化并发才是王道!

我们先定义获取用户信息任务: 再定义获取订单信息任务: 然后再构造线程池并执行任务: 输出结果为: 看上去一切都刚刚好,但是,如果获取订单信息时出错了,此时会是什么现象呢?修改获取…

PoC免写攻略

在网络安全领域,PoC(Proof of Concept)起着重要的作用,并且在安全研究、漏洞发现和漏洞利用等方面具有重要的地位。攻击方视角下,常常需要围绕 PoC 做的大量的工作。常常需要从手动测试开始编写 PoC,再到实…

SAP - 采购价格确定 ③ 抬头条件和组条件

抬头条件和组条件 当我们创建一个具有多个行项目的采购订单时,我们经常需要条件可以应用到所有的行项目中。相应的,条件也可以应用到特定的行项目。在R/3系统中,条件可以涉及采购凭证的单个行项目(项目条件),多个行项目(组条件)或所有的行项目(抬头条件)。 一些标准…

计算机/大数据毕业设计-基于Python的动漫数据分析可视化系统的设计与实现

基于Python的动漫数据分析可视化系统的设计与实现 设计爬虫程序爬取哔哩哔哩动漫数据信息 后端使用flask框架,数据库使用Mysql8.0,可视化使用echarts 部分代码如下: # 保存所有动漫信息 all_anime_infos [] # 保存到文件中 file_writer …