设计模式-依赖注入模式

设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • 依赖注入和控制反转的区别
    • 代码示例
      • 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.mzph.cn/news/579896.shtml

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

相关文章

STM32F407-14.3.10-表73具有有断路功能的互补通道OCx和OCxN的输出控制位-1x001

如上表所示&#xff0c;MOE1&#xff0c;OSSR0&#xff0c;CCxE0&#xff0c;CCxNE1时&#xff0c;OCx输出状态取决于GPIO端口上下拉状态&#xff0c;OCxN输出状态取决于OCx_REF与极性选择&#xff08;CCxNP&#xff09;。 -------------------------------------------------…

【头歌实训】Spark 完全分布式的安装和部署(新)

文章目录 第1关&#xff1a; Standalone 分布式集群搭建任务描述相关知识课程视频Spark分布式安装模式主机映射免密登录准备Spark安装包配置环境变量修改 spark-env.sh 配置文件修改 slaves 文件分发安装包启动spark验证安装 编程要求测试说明答案代码 第1关&#xff1a; Stand…

C++ Qt开发:QSqlDatabase数据库组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍QSqlDatabase数据库模块的常用方法及灵活运用…

Cloudstack多个管理服务器节点

https://docs.cloudstack.apache.org/en/4.18.0.0/adminguide/reliability.html 参考翻译&#xff1a; 代理上支持多个管理服务器 在具有多个管理服务器的Cloudstack环境中&#xff0c;可以根据算法配置代理&#xff0c;将其连接到哪个管理服务器。这对于内部负载均衡器或高可…

湘潭大学软件工程头歌多选题-期末考试复习资料

说明 从后面往前面来复习&#xff0c;章节对于考试不重要&#xff0c;重要的是有一个印象 主要不是内容&#xff0c;主要是挑一些可能会选错的来记录&#xff0c;一眼的就不再进行记录 其中加入了笔者的一些思考&#xff0c;不一定准确和严谨&#xff0c;仅供参考 题目 以…

git中关于submodule的操作

添加submodule git submodule add <url>t 3rd/submodule1如果出错&#xff0c;执行 git rm --cached 3rd/submodule1后期执行 git submodule sync git submodule update --init --recursive

【机器学习】人工智能概述

人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使机器能够像人一样思考、学习和执行任务的学科。它是计算机科学的一个重要分支&#xff0c;涉及机器学习、自然语言处理、计算机视觉等多个领域。 人工智能的概念最早可以追溯到20世…

3.docker 安装失败

1、错误描述 2、报错前操作 ① 安装yum工具 yum install -y yum-utils \device-mapper-persistent-data \lvm2 --skip-broken ② 更新本地镜像源 # 设置docker镜像源 yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo…

知识笔记(五十九)———css 美化滚动条样式

ChatgGPT4.0国内站点: 海鲸AI-支持GPT(3.5/4.0)&#xff0c;文件分析&#xff0c;AI绘图 在CSS中&#xff0c;你可以使用伪元素::-webkit-scrollbar以及相关的伪元素来为Webkit浏览器&#xff08;如Chrome和Safari&#xff09;自定义滚动条的样式。以下是一些基本的CSS规则&am…

扫描全能王启动鸿蒙原生应用开发,系HarmonyOS NEXT智能扫描领域首批

近期&#xff0c;“鸿蒙合作签约暨扫描全能王鸿蒙原生应用开发启动仪式”&#xff08;简称“签约仪式”&#xff09;正式举行。合合信息与华为达成鸿蒙合作&#xff0c;旗下扫描全能王将基于HarmonyOS NEXT正式启动鸿蒙原生应用开发。据悉&#xff0c;扫描全能王是鸿蒙在智能扫…

DM、HIVE和Kingbase8(人大金仓数据库)给列增加备注

DM数据库给列增加备注 1、创建表 CREATE TABLE test222 ( id int NOT NULL PRIMARY KEY, name varchar(1000) DEFAULT NULL, email varchar(1000) DEFAULT NULL, phone varchar(1000) DEFAULT NULL ) 2、给列添加注释 comment on column TEST222.NAME is 这是一个列注释; 例如…

CentOS 7 firewalld+ipset+定时任务防御ssh暴力破解——筑梦之路

对于暴露在公网上的linux服务器&#xff0c;很容易被暴力破解登陆&#xff0c;为了增强服务器的安全性&#xff0c;因此对于ssh安全加固是很有必要的&#xff0c;这里主要介绍centos7 系统如何使用ipsetfirewalld定时任务来对ssh服务进行安全加固。 定义firewalld ipset fire…

centos 安装java + tomcat

centos 安装java tomcat tomcat支持jsp&#xff0c;apache2支持php 1, 查看是否已经安装java并卸载 yum list installed | grep java\|jdk\|gcj\|jreyum remove -y 2,安装JAVA-JDK lscpu | grep Architecture # 查看系统架构&#xff0c; x86_64yum list |grep jdk | grep…

说说 Spring Boot 实现接口幂等性有哪几种方案?

一、什么是幂等性 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂等…

关联规则+聚类分析+分类算法(数据挖掘)

3.关联规则 经典案例 : 尿布与啤酒的故事&#xff1b; 基本概念 : 设I {i1,i2,....im}是项(Item)的集合。 D 是 事务(transaction)的集合(事务数据库)。 事务T是项的集合&#xff0c;且对每个事务具有唯一的标识: 事务号&#xff0c;记作TID; 设A是I中的一个项集&#xf…

2024黑龙江省职业院校技能大赛暨国赛选拔赛应用软件系统开发赛项(高职组)赛题第3套

2024黑龙江省职业院校技能大赛暨国赛选拔赛 应用软件系统开发赛项&#xff08;高职组&#xff09; 赛题第3套 目录&#xff1a; 需要竞赛源码资料可以私信博主。 竞赛说明 模块一&#xff1a;系统需求分析 任务1&#xff1a;制造执行MES—质量管理—来料检验&#xff08;…

Linux部署ELK

大家好&#xff0c;我是升仔 引言 在复杂的系统架构中&#xff0c;日志管理是一个关键的环节。ELK栈提供了一个高效的解决方案&#xff0c;能够帮助我们快速定位问题、分析数据&#xff0c;并实现实时监控。部署ELK栈是一项挑战&#xff0c;但收益巨大。 基础安装和配置 环境准…

Redis分布式缓存之主从哨兵分片集群

Redis主从 数据同步原理 Redis哨兵 Redis分片集群 集群伸缩&#xff1a;在集群中插入或删除某个节点 集群故障转移

Android 13 - Media框架(28)- ACodec(五)

前面几节我们了解了OMXNodeInstance是如何处理setPortMode、allocateBuffer、useBuffer的&#xff0c;这一节我们再回到ACodec&#xff0c;来看看 ACodec start 的其他部分。 我们首先来回顾一下&#xff0c;ACodec start 的状态切换以及处理的事务&#xff0c;我们用一张不太准…

【第2讲】原理介绍和权限开通

系列文章目录 第1讲:Python环境的下载和安装第2讲:免费开通权限第3讲:1行代码,自动发正文第4讲:1行代码,自动发正文+附件第5讲:自动批量发送第6讲:1行代码,自动下载邮件的附件提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录…