设计模式-依赖注入模式

设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • 依赖注入和控制反转的区别
    • 代码示例
      • 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 = dependency

    def perform_task(self):
        self.dependency.do_something()

# 定义容器类,负责创建和注入依赖对象
class Container:
    def __init__(self):
        self.dependencies = {}

    def add_dependency(self, clazz, instance):
        self.dependencies[clazz] = instance

    def 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之间的依赖关系,提高应用程序的可维护性和可扩展性。

在这里插入图片描述

设计模式-工厂模式

设计模式-适配器模式

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

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

相关文章

【宇宙猜想】AR文创入驻今日美术馆、北京天文馆等众多展馆,在AR互动中感受科技魅力!

近日&#xff0c;由「宇宙猜想」推出的AR系列文创产品先后入驻今日美术馆、北京天文馆、国家自然博物馆、上海天文馆、国家海洋馆、中华手工展馆等各大馆场并与其展开相关合作。 「宇宙猜想」致力于创造虚拟空间价值&#xff0c;用AR技术与文创产品碰撞出新的火花&#xff0c;为…

【星海随笔】网络运维

[rootlocalhost ~]# source admin-openrcRabbitMQ 工作机理 1.客户端连接到消息队列服务器&#xff0c;打开一个channel。 2.客户端声明一个exchange&#xff0c;并设置相关属性。 3.客户端声明一个queue&#xff0c;并设置相关属性。 4.客户端使用routing key&#xff0c;在ex…

初识k8s

k8s: kubernetes:八个字母省略&#xff0c;就是k8s 自动部署&#xff0c;自动扩展和管理容器化部署的应用程序的一个开源系统 k8s是负责自动化运维管理多个容器化程序的集群&#xff0c;是一个功能强大得容器编排工具 分布式和集群化的方式进行容器管理 市面上常用的版本&…

HTTP小记2

目录 HTTP/1.1优化 QUIC协议 路由器 RTT&#xff08;Round-Trip Time&#xff09; 计算机网络体系结构 体系结构各层在整个过程中的作用 HTTP/1.1优化 1.通过缓存技术来避免/减少发送HTTP请求 2.减少HTTP请求的次数 将原本由客户端处理的重定向请求&#xff0c;交给代理…

alertmanage调用企业微信告警(k8s内部署)

一、前言 alertmanage调用企业微信应用告警会比直接使用钉钉告警更麻烦一点&#xff0c;调用企业微信应用告警需要在应用内配置企业可信ip&#xff0c;不然调用企业微信接口就会报错&#xff0c;提示ip地址有风险 二、部署 先自行创建企业微信&#xff0c;再使用管理后台创建应…

机器视觉实战应用:手势、人脸、动作以及手势鼠标构建(一)

CV实战应用手势、人脸、动作以及手势鼠标构建&#xff08;一&#xff09;总起 核心思想 手势识别是一种常见的计算机视觉应用&#xff0c;它可以通过摄像头或者预先录制的视频图像来追踪和识别人类手势。手势识别的应用非常广泛&#xff0c;例如在游戏、虚拟现实、人机交互等…

RuoYi-Cloud集成DataRoom大屏设计器

基于RuoYi-Cloud 3.6.3 版本集成 先贴一下开源地址: https://gitee.com/wxjstudy/jove-fast DataRoom开源地址: https://gitee.com/gcpaas/DataRoom 后端 新建modules 启动类 增加注解扫描,以及配置分页插件 import com.baomidou.mybatisplus.extension.plugins.MybatisPlu…

Leetcode—54.螺旋矩阵【中等】

2023每日刷题&#xff08;七十&#xff09; Leetcode—54.螺旋矩阵 实现代码 class Solution { public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> ans;int m matrix.size();int n matrix[0].size();int row 0, col…

虚拟环境和Pycharm中均有transforms仍报ModuleNotFoundError:No module named ‘transformers‘

问题&#xff1a;运行新模型&#xff0c;配置了新环境&#xff0c;下载了包后&#xff0c;仍然报ModuleNotFoundError&#xff1a;No module named transformers 错误。 查看Pycharm解释器&#xff1a; 没问题&#xff01;&#xff01;&#xff01;&#xff1f; 命令行查看虚…

阿赵UE学习笔记——5、创建关卡元素

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   之前介绍了从空白模板创建关卡&#xff0c;接下来尝试着在这个空白的世界里面&#xff0c;创建一些内容。 一、创建地面 1、创建面片作为地面 创建——形状——平面&#xff0c;可以创建一个面片 在细节面板设置合适的…

【广州华锐互动】VR科技科普展厅平台:快速、便捷地创建出属于自己的虚拟展馆

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经在许多领域取得了显著的成果。尤其是在展馆设计领域&#xff0c;VR科技科普展厅平台已经实现了许多令人瞩目的新突破。 VR科技科普展厅平台是广州华锐互动专门为企业和机构提供虚拟展馆设计和制作的在线平台。通过这个平台&…

【微服务核心】Spring Boot

Spring Boot 文章目录 Spring Boot1. 简介2. 开发步骤3. 配置文件4. 整合 Spring MVC 功能5. 整合 Druid 和 Mybatis6. 使用声明式事务7. AOP整合配置8. SpringBoot项目打包和运行 1. 简介 SpringBoot&#xff0c;开箱即用&#xff0c;设置合理的默认值&#xff0c;同时也可以…

设计模式-单例模式(结合JVM基础知识)

1.定义介绍 所谓单例模式&#xff0c;是指在程序运行时&#xff0c;整个JVM中只有一个该类的实例对象 2. 单例模式的优点 复用性高&#xff0c;节省内存资源。类的加载、连接、初始化、使用都要占用虚拟机内存空间&#xff0c;因此&#xff0c;频繁创建对象会造成资源浪费&a…

文件夹共享(普通共享和高级共享的区别)防火墙设置(包括了jdk安装和Tomcat)

文章目录 一、共享文件1.1为什么需要配置文件夹共享功能&#xff1f;1.2配置文件共享功能1.3高级共享和普通共享的区别&#xff1a; 二、防火墙设置2.1先要在虚拟机上安装JDK和Tomcat供外部访问。2.2设置防火墙&#xff1a; 一、共享文件 1.1为什么需要配置文件夹共享功能&…

IDEA使用之打包Jar,指定main方法

前言 在某些场景&#xff0c;可能会遇到将非Spring项目打包的情况&#xff0c;我们不需要Tomcat服务器部署&#xff0c;只需要执行指定的main方法即可&#xff0c;这种情况打包成jar就比较方便了。 操作步骤 打包结果默认在项目的out目录下 使用 java -jar xxx.jar

企业微信自建应用获取用户信息

一.前言 开发企业微信自建应用的时候难免会有获取企微个人信息的业务需求,这篇博客将详细说明企微自建应用获取userId的具体流程. 二.基本概念介绍 2.1 corpid 每个企业都拥有唯一的corpid&#xff0c;获取此信息可在管理后台“我的企业”&#xff0d;“企业信息”下查看“企业…

(1)llvm学习词法分析器

首先是Token取值 下面两个值记录当前识别出来的token单元的字面量 首先是空字符&#xff0c;然后如果是空字符&#xff0c;就读下一个字符&#xff0c;知道这个字符不是空为止&#xff0c;也就是LastChar出循环的时候是下一个不为空的字符,下面两个值是记录实际值用于后续处理 …

VR渲染器怎么用之自适应图像采样器,可解决渲染黑图问题

大家好&#xff0c;相信刚接触到vr渲染器时&#xff0c;会vr的图像采样器感到迷茫&#xff0c;如何使用图像采样器&#xff1f;图像采样器有何用呢&#xff1f; 今天便为大家讲解vr中的自适应DMC图像采样器的运用。 说明&#xff1a;高版本渲染器中的渲染块整合了原有的“固定…

PYTHON入门级游戏开发:宇宙飞船游戏两万字详析

手讲解超详细python入门游戏项目‘打外星飞船’手把&#xff08;一&#xff09; 由于内容比较多&#xff0c;这里会分为五篇文章来讲解&#xff0c;从页面的创建、飞船控制、射击、外星人创建、射杀外星人五片来展开。 做一个窗口和设置响应用户 import sysimport pygame&qu…

STM32逆变器方案

输入电压&#xff1a; 额定输入电压&#xff1a;DC110V 输入电压范围&#xff1a;DC77-137.5V 额定输出参数 电压&#xff1a;200V5%&#xff08;200VAC~240VAC 可调&#xff09; 频率&#xff1a; 42Hz0.5Hz&#xff08;35-50 可调&#xff09; 额定输出容量&#xff1a;1…