设计模式-依赖注入模式

设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • 依赖注入和控制反转的区别
    • 代码示例
      • Java实现依赖注入模式
      • Python实现依赖注入模式
    • 依赖注入模式在spring中的应用


模式介绍

依赖注入(Dependency Injection,简称DI)是一种面向对象编程中的设计模式,它的目的是将一个对象所依赖的其他对象的创建过程从该对象本身中分离出来,以便更好地实现解耦和可测试性。

在DI模式中,对象不是通过自己创建所需要的依赖对象,而是通过构造函数、属性或接口传递进来。主要有以下几种方式:

  1. 构造函数注入(Constructor Injection):依赖对象通过被依赖对象的构造函数传入。这种方式是DI的主要方式,也是最简单的一种方式。它可以保证依赖对象的创建和注入是在同一时间完成的,因此可以确保依赖对象的可用性。适用于依赖对象需要在整个对象生命周期中都存在的情况,例如一个数据库连接对象。
  2. 属性注入(Property Injection):依赖对象通过被依赖对象的公共属性进行注入。
  3. 接口注入(Interface Injection):依赖对象通过实现被依赖对象的接口进行注入。

依赖注入的意义在于:

  1. 保证客户类仅仅与其依赖的服务类耦合,而不与服务类的子类型耦合,使得程序符合OCP或依赖于抽象类型原则。
  2. 不需声明全局公共的服务类对象,而是通过依赖注入(伸手-等待)来获取:在接受注入时声明所依赖的服务对象(伸手),框架会在初始化时将对象传递进来(等待)。

在这里插入图片描述

模式特点

依赖注入的主要特点包括:

  1. 降低耦合度 :依赖注入的核心思想是将对象之间的依赖关系分离出来,将原本紧耦合的对象变得松耦合,使得各个模块之间的依赖关系减少,有利于代码的复用和测试。
  2. 提高可扩展性 :由于依赖关系是通过外部方式注入的,因此当需要添加新的功能或模块时,只需要在配置文件中添加新的依赖关系,而不需要修改原有的代码,从而提高了系统的可扩展性。
  3. 便于测试和调试 :通过外部方式注入依赖关系,可以很容易地模拟和控制依赖对象的行为,便于进行单元测试和调试。
  4. 增强代码的可读性和可维护性 :通过使用依赖注入,代码更加清晰易懂,同时也可以减少代码中的硬编码,使得代码更加灵活、可维护。

在这里插入图片描述

应用场景

依赖注入模式的应用场景主要包括以下几个方面:

  1. 单元测试 :在单元测试中,依赖注入模式可以使得测试更加简单和有效。通过模拟依赖对象的行为,可以很容易地对被测试对象进行隔离和测试。
  2. 插件式开发 :在插件式开发中,依赖注入模式可以使得插件之间的依赖关系更加清晰和灵活。通过配置文件或注解等方式,可以很容易地管理和控制插件之间的依赖关系。
  3. 多环境配置 :在不同的运行环境中,可能需要使用不同的依赖对象。通过依赖注入模式,可以很容易地根据不同的环境配置来注入不同的依赖对象,从而提高了代码的灵活性和可维护性。
  4. 框架开发 :在框架开发中,依赖注入模式可以使得框架更加灵活和可扩展。通过提供统一的依赖注入机制,可以使得框架的使用者更加方便地使用和管理框架提供的各种服务。

在这里插入图片描述

依赖注入和控制反转的区别

控制反转(Inversion of Control,简称IoC)依赖注入(Dependency Injection,简称DI)是两个相关但略有不同的概念。

控制反转是创建对象实例的控制权从代码控制剥离到IoC容器控制,侧重于原理。依赖注入则是在创建对象实例时,为这个对象注入属性值或其它对象实例,侧重于实现。

简单来说,依赖注入是从应用程序的角度在描述:应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源(对象、文件等)。

在这里插入图片描述

代码示例

Java实现依赖注入模式

以下是一个简单的Java实现依赖注入模式的示例:

// 定义依赖对象
public class Dependency {public void doSomething() {System.out.println("Dependency is doing something.");}
}// 定义服务类,接受依赖对象
public class Service {private Dependency dependency;// 通过构造函数注入依赖对象public Service(Dependency dependency) {this.dependency = dependency;}public void performTask() {dependency.doSomething();}
}// 定义容器类,负责创建和注入依赖对象
public class Container {private Map<Class<?>, Object> dependencies = new HashMap<>();public <T> void addDependency(Class<T> clazz, T instance) {dependencies.put(clazz, instance);}public Object getDependency(Class<?> clazz) {return dependencies.get(clazz);}
}// 使用容器创建服务对象并注入依赖对象
public class Main {public static void main(String[] args) {Container container = new Container();Dependency dependency = new Dependency();container.addDependency(Dependency.class, dependency);Service service = new Service((Dependency) container.getDependency(Dependency.class));service.performTask(); // 输出 "Dependency is doing something."}
}

在这个示例中,我们定义了一个依赖对象Dependency和一个服务类Service,服务类通过构造函数接受依赖对象。然后我们定义了一个容器类Container,负责创建和注入依赖对象。在主程序中,我们创建了一个容器实例,将依赖对象添加到容器中,然后通过容器实例创建服务对象并注入依赖对象。最后,我们调用服务对象的performTask()方法,输出依赖对象的doSomething()方法的结果。

Python实现依赖注入模式

以下是Python实现依赖注入模式的一个示例:

# 定义依赖对象
class Dependency:def do_something(self):print("Dependency is doing something.")# 定义服务类,接受依赖对象
class Service:def __init__(self, dependency):self.dependency = dependencydef perform_task(self):self.dependency.do_something()# 定义容器类,负责创建和注入依赖对象
class Container:def __init__(self):self.dependencies = {}def add_dependency(self, clazz, instance):self.dependencies[clazz] = instancedef get_dependency(self, clazz):return self.dependencies.get(clazz)# 使用容器创建服务对象并注入依赖对象
def main():container = Container()dependency = Dependency()container.add_dependency(Dependency, dependency)service = Service(container.get_dependency(Dependency))service.perform_task()  # 输出 "Dependency is doing something."if __name__ == "__main__":main()

在这个示例中,我们定义了一个依赖对象Dependency和一个服务类Service。服务类通过构造函数接受依赖对象。然后我们定义了一个容器类Container,负责创建和注入依赖对象。在主程序中,我们创建了一个容器实例,将依赖对象添加到容器中,然后通过容器实例创建服务对象并注入依赖对象。最后,我们调用服务对象的perform_task()方法,输出依赖对象的do_something()方法的结果。

在这里插入图片描述

依赖注入模式在spring中的应用

在Spring框架中,依赖注入是一种核心特性,用于管理Bean之间的依赖关系。依赖注入允许在运行时动态地将依赖对象注入到Bean中,从而降低了对象之间的耦合度,提高了代码的可维护性和可测试性。

Spring提供了多种方式来实现依赖注入,包括注解和XML配置。使用注解的方式,可以在Bean的定义中添加相应的注解(如@Autowired@Resource等),来指定注入的依赖对象。而使用XML配置的方式,可以在配置文件中定义Bean之间的关系,Spring容器在启动时会解析这些配置并自动注入依赖对象。

依赖注入主要有两种方式:构造器注入和Setter注入。构造器注入是通过Bean的构造方法来注入依赖对象,而Setter注入则是通过设置器方法来注入依赖对象。在Spring中,可以通过@Autowired注解来实现构造器注入,而通过@Resource注解或XML配置来实现Setter注入。

此外,Spring还提供了@Qualifier注解来指定具体的依赖对象。当Spring容器中存在多个符合条件的对象时,可以使用@Qualifier注解来指定要注入的具体对象。

Spring中的依赖注入模式使得代码更加清晰、灵活和易于维护,是Spring框架的核心特性之一。通过依赖注入,可以有效地管理Bean之间的依赖关系,提高应用程序的可维护性和可扩展性。

在这里插入图片描述

设计模式-工厂模式

设计模式-适配器模式

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

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

相关文章

【目标跟踪】解决多目标跟踪遮挡问题

文章目录 前言一、判定遮挡目标二、扩展目标框三、结论 前言 目标跟踪在发生遮挡时&#xff0c;极其容易发生Id Switch。网上许多算法忽视跟踪遮挡问题,同时网上相关资料也很少。博主为了解决跟踪遮挡&#xff0c;翻阅大量论文。分享其中一篇论文。论文链接&#xff1a;https:…

网站被恶意扫描怎么办(上WAF)

在网络安全领域&#xff0c;有一大类工具被广泛使用&#xff0c;且作用不可忽视&#xff0c;它就是网络安全扫描器。扫描器是一种专门设计用来评估计算机、网络或者应用中已知的弱点的计算机程序&#xff0c;但是很多人恶意使用&#xff0c;找到网站弱点进行攻击。 扫描器的种…

Vue和React的运行时,校验引入包的上下文差异

背景 系统使用 webpack 5 模块联邦实现微前端&#xff0c;有关如何实现跨应用的代码共享&#xff0c;可参考 如何优雅的实现跨应用的代码共享 里的第三大点。 总之&#xff0c;这里是其他应用使用了某个应用共享出来的reg文件&#xff0c;引入方式为&#xff1a; import REG …

LSTM的记忆能力实验 [HBU]

目录 模型构建 LSTM层 模型训练 多组训练 模型评价 模型在不同长度的数据集上的准确率变化图 模型汇总 总结 长短期记忆网络&#xff08;Long Short-Term Memory Network&#xff0c;LSTM&#xff09;是一种可以有效缓解长程依赖问题的循环神经网络&#xff0e;LSTM 的…

ARM12.26

整理三个按键中断代码 key_it.h #ifndef __KEY_IT_H__ #define __KEY_IT_H__ #include"stm32mp1xx_gpio.h" #include"stm32mp1xx_gic.h" #include"stm32mp1xx_exti.h" #include"stm32mp1xx_rcc.h" #include"led.h" void k…

blender使用faceit绑定自己的表情动作

blender使用faceit绑定自己的表情控制模型 faceit是个神器&#xff0c;来记录一下如何让表情动起来保持相对位置头部分离&#xff0c;方便后续绑定faceitfaceit的注册rig生成地标Animate可以修正表情烘培之前记得保存使用Faceit的整个流程 faceit是个神器&#xff0c;来记录一下…

工具系列:TensorFlow决策森林_(3)使用dtreeviz可视化

文章目录 介绍设置安装 TF-DF 和 dtreeviz导入库 可视化分类树加载、清洗和准备数据分割训练/测试集并训练模型训练一个随机森林分类器显示决策树检查叶节点统计信息决策树如何对实例进行分类特征空间划分 可视化回归树加载、清洗和准备数据分割训练/测试集并训练模型训练一个随…

智能优化算法应用:基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.协作搜索算法4.实验参数设定5.算法结果6.…

nginx-proxy-manager初次登录502 bad gateway

nginx-proxy-manager初次登录502 bad gateway 按照官方docker-compose安装后,页面如下: 默认账户密码: adminexample.com/changeme点击sign in,提示Bad Gateway 打开调试 重装后依然如此,最后查阅githup issue 找到答案 https://github.com/NginxProxyManager/nginx-proxy-…

【操作系统】探究文件系统奥秘:创建proc文件系统的解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;Linux专栏&#xff1a;《探秘Linux | 操作系统解密》⏰诗赋清音&#xff1a;月悬苍穹泛清辉&#xff0c;梦随星河徜徉辉。情牵天际云千层&#xff0c;志立乘风意自飞。 ​ 目录 &a…

web前端项目-七彩夜空烟花【附源码】

web前端项目-七彩动态夜空烟花【附源码】 本项目仅使用了HTML&#xff0c;代码简单&#xff0c;实现效果绚丽&#xff0c;且本项目代码直接运行即可实现&#xff0c;无需图片素材&#xff0c;接下来让我们一起实现一场美丽的烟花秀叭 运行效果&#xff1a;鼠标点击和移动可控制…

tamarin manual总结笔记5(使用流程的模型规格)

使用流程的模型规格 在本节中&#xff0c;我们提供了一个非正式的描述过程演算现在集成在Tamarin。它被称为SAPIC&#xff0c;即“状态应用PI-Calculus”。该模型的全部细节可以在(Kremer and k nnemann 2016)和(Backes et al 2017)中找到。 可以根据规则或作为(单个)流程对协…

云计算:现代技术的基本要素

众所周知&#xff0c;在儿童教育的早期阶段&#xff0c;幼儿园都会传授塑造未来行为的一些基本准则。 今天&#xff0c;我们可以以类似的方式思考云计算&#xff1a;它已成为现代技术架构中的基本元素。云现在在数字交互、安全和基础设施开发中发挥着关键作用。云不仅仅是另一…

C#教程(四):多态

1、介绍 1.1 什么是多态 在C#中&#xff0c;多态性&#xff08;Polymorphism&#xff09;是面向对象编程中的一个重要概念&#xff0c;它允许不同类的对象对同一消息做出响应&#xff0c;即同一个方法可以在不同的对象上产生不同的行为。C#中的多态性可以通过以下几种方式实现…

Java API 操作Docker浅谈

背景&#xff1a; 使用com.github.docker-java库可以很方便地在Java中操作Docker。下面是一个详细的教程&#xff0c;包括创建镜像、创建容器、启动容器、停止容器和删除容器的步骤以及每一步的说明。 前提&#xff1a; 首先&#xff0c;在你的Java项目中添加com.github.doc…

ARM 汇编语言知识积累

博文参考&#xff1a; arm中SP&#xff0c;LR&#xff0c;PC寄存器以及其它所有寄存器以及处理器运行模式介绍 arm平台根据栈进行backtrace的方法-腾讯云开发者社区-腾讯云 (tencent.com) 特殊功能寄存器&#xff1a; SP&#xff1a; 即 R13&#xff0c;栈指针&#xff0c;…

渗透测试——1.4主动扫描

主动扫描是别人可以发觉的情报收集 一、nmap的使用 1.nmap<目标主机>:最常用的扫描方式 有nmap版本、扫描时间 “host is up”表示目标主机处于开机状态、“not shown”未开放端口 有四个端口是开的&#xff08;135.139.445.912&#xff09; 2.nmap -p<端口范围…

NET中使用Identity+CodeFirst+Jwt实现登录、鉴权

目录 前言 一、创建上下文类 1.自定义MyContext上下文类继承IdentityDbContext 2.在Program中添加AddDbContext服务 二、使用Migration数据迁移 1.在控制台中 依次使用add-migration 、updatebase 命令 2.如何修改表名 3.如何自定义字段 三、使用Identity实现登录、修改密码 …

【JAVA】黑马MybatisPlus 学习笔记【终】【插件功能】

4.插件功能 MybatisPlus提供了很多的插件功能&#xff0c;进一步拓展其功能。目前已有的插件有&#xff1a; PaginationInnerInterceptor&#xff1a;自动分页TenantLineInnerInterceptor&#xff1a;多租户DynamicTableNameInnerInterceptor&#xff1a;动态表名OptimisticL…

【小白专用】C# 压缩文件 ICSharpCode.SharpZipLib.dll效果:

插件描述&#xff1a; ICSharpCode.SharpZipLib.dll 是一个完全由c#编写的Zip, GZip、Tar 、 BZip2 类库,可以方便地支持这几种格式的压缩解压缩, SharpZipLib 的许可是经过修改的GPL&#xff0c;底线是允许用在不开源商业软件中&#xff0c;意思就是免费使用。具体可访问ICSha…