C++中的依赖注入

news2024/11/13 11:20:57

目录

1.概述

2.构造函数注入

3.setter方法注入

4.接口注入

5.依赖注入框架

6.依赖注入容器

7.依赖注入框架的工作原理

8.依赖注入的优势

9.总结


1.概述

        依赖注入是一种设计模式,它允许我们在不直接创建对象的情况下为对象提供其依赖项;它通过将对象的依赖关系从内部实现转移到外部配置,以此来实现松耦合;这使得我们的代码更易于测试、维护和扩展。

        然而,在C++中实现依赖注入(Dependency Injection, DI)通常比在一些其他语言(如Java或.NET)中更具挑战性,因为C++是一种静态类型语言,且没有内建的依赖注入框架。不过,通过一些设计模式和技术,我们可以在C++项目中实现依赖注入。

        依赖注入主要有以下三种方式:

  1. 构造函数注入:将被依赖对象通过构造函数的参数传递依赖对象,并且在初始化对象的时候注入。

  2. 属性注入:通过属性(成员变量)来传递依赖对象。

  3. 接口注入:通过接口方法传递依赖对象。

     在C++中,构造函数注入和属性注入是最常用的两种方式。

2.构造函数注入

        构造函数注入是一种最简单且最常用的依赖注入方式,通过构造函数参数来传递依赖对象。示例代入如下:

class Dependency { 
public: 
    void doSomething() { 
        // 实现 
    } 
}; 

class MyClass { 
private: 
    Dependency* dep; 

public: 
    MyClass(Dependency* dep) : dep(dep) {} 

    void someMethod() { 
        dep->doSomething(); 
    } 
}; 

// 使用 
Dependency dep; 
MyClass myClass(&dep); 
myClass.someMethod();

在上述代码中,MyClass类通过构造函数接收Dependency对象的引用,从而实现了依赖注入。

3.setter方法注入

        通过类的成员函数(通常是setter)来注入依赖项。这种方式提供了更多的灵活性,但也可能导致类在使用前未正确配置的风险。示例代码如下:

class MyClass {  
private:  
    Dependency* dep = nullptr;  
  
public:  
    void setDependency(Dependency* dep) {  
        this->dep = dep;  
    }  
  
    void useDependency() {  
        if (dep) {  
            dep->doSomething();  
        }  
    }  
};  
  
// 使用  
Dependency dep;  
MyClass myClass;  
myClass.setDependency(&dep);  
myClass.useDependency();

在此例中,MyClass类通过setDependency方法接收Dependency对象,从而实现了依赖注入。

4.接口注入

        依赖类必须要实现指定的接口(在C++中通常通过纯虚函数实现的抽象基类),然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。

        示例代码如下:

class IDependency {  
public:  
    virtual void doSomething() = 0;  
    virtual ~IDependency() {}  
};  
  
class Dependency : public IDependency {  
public:  
    void doSomething() override {  
        // 实现细节  
    }  
};  
  
class MyClass {  
private:  
    IDependency* dep;  
  
public:  
    MyClass(IDependency* dep) : dep(dep) {}  
  
    void useDependency() {  
        dep->doSomething();  
    }  
};  
  
// 使用  
Dependency dep;  
MyClass myClass(&dep);  
myClass.useDependency();

5.依赖注入框架

        虽然C++没有内置的依赖注入框架,但有一些第三方库提供了依赖注入的支持,如Boost.DI、Inject或C++DI等。这些库通常提供了更高级的特性和更简洁的语法来管理依赖项。

1) Spring(Java):Spring框架是Java生态系统中最流行的依赖注入框架之一。它提供了丰富的功能,包括依赖注入、面向切面编程(AOP)、事务管理等。Spring的依赖注入是通过其IoC容器来实现的,支持多种注入方式和配置方式。

2) Google Guice(Java):Guice是一个轻量级的Java依赖注入框架,它提供了比Spring更简洁的API和更快的启动速度。Guice也支持构造函数注入、Setter方法注入和字段注入等多种注入方式。

3) Dagger(Java/Kotlin):Dagger是Google开发的一个基于编译时注解处理的依赖注入框架,它提供了比Guice更快的性能。Dagger强制使用构造函数注入,并通过代码生成来优化依赖注入的性能。

4) Boost.DI(C++):虽然C++没有内置的依赖注入框架,但Boost.DI是一个流行的C++依赖注入库。它提供了类似于Java依赖注入框架的功能,允许开发者在C++项目中实现依赖注入。

5) Wire(Go):Wire是由Google开源的一个用Go语言实现的依赖注入代码生成工具。它能够根据开发者编写的代码生成相应的依赖注入Go代码,实现编译期间的依赖注入。

6.依赖注入容器

        在C++中,没有像Spring或.NET Core那样的内置依赖注入容器。但是,你可以使用第三方库(如Boost.DI或Inject)或自己实现一个简单的容器。

// 假设有一个简单的DI容器 
class DIContainer { 
// 容器实现,可以存储和检索依赖项 
}; 

// 容器配置 
DIContainer container; 
container.register<Dependency>(); 
container.register<MyClass, std::unique_ptr<MyClass>>([](DIContainer& c) { 
return std::make_unique<MyClass>(c.resolve<Dependency*>()); 
}); 

// 使用 
auto myClass = container.resolve<std::unique_ptr<MyClass>>(); 
myClass->someMethod();

7.依赖注入框架的工作原理

        依赖注入框架通过容器(IoC容器)来管理对象的生命周期和依赖关系。开发者只需定义好类的依赖关系,框架就会在运行时或编译时自动将这些依赖注入到对象中。这样,类的创建和使用就被解耦了,提高了代码的灵活性和可重用性。

        依赖注入框架的工作原理通常包括以下几个步骤:

定义依赖:在代码中通过注解、XML配置文件或其它配置类等方式定义类的依赖关系、对象的属性、生命周期等。

创建容器:创建IoC容器,它负责管理和维护应用程序中的所有对象,包括对象的初始化、销毁、事件触发等。这有助于确保对象在使用过程中的正确性和稳定性。

解析依赖:容器在创建对象时,会根据定义的依赖关系自动查找并注入所需的依赖项。

对象使用:对象被创建并注入依赖后,就可以像往常一样使用了。但是,由于依赖关系是由容器管理的,因此对象的创建和使用都被解耦了。

8.依赖注入的优势

        依赖注入框架的优势主要体现在以下几个方面:

降低耦合度:通过解耦对象的创建和使用,降低了代码之间的耦合度,提高了代码的可维护性和可扩展性。

提高可测试性:由于依赖关系可以在外部定义和配置,因此可以轻松地替换为模拟对象(Mock Object)进行测试,提高了代码的可测试性。

支持模块化开发:通过依赖注入,可以将应用程序划分为多个独立的模块,并通过配置来组装这些模块,支持模块化开发。

9.总结

        依赖注入框架是一种强大的软件设计模式实现工具,它能够帮助开发者降低代码的耦合度,提高代码的可测试性、可维护性和可扩展性。通过外部配置或代码逻辑将依赖项注入到目标对象中,依赖注入框架使得对象的创建、配置和生命周期管理变得更加灵活和高效。

推荐阅读

面向对象设计之依赖反转原则

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

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

相关文章

学习c语言第十四天(调试+练习)

一、调试 所有发生的事情都一定有迹可循&#xff0c;如果问心无愧&#xff0c;就不需要掩盖也就没有迹象了&#xff0c;如果问心有愧 就必然需要掩盖&#xff0c;那就一定会有迹象&#xff0c;迹象越多就越容易顺藤而上&#xff0c;这就是推理的途径。 顺着这条途径顺流而下就…

广东省某地区智慧水务平台全面升级启航(案例解析)

项目背景 随着物联网、人工智能、大数据、数字孪生等技术的应用&#xff0c;对精准调控、漏损控制、可视化管理、节能降耗、高效指挥等方面的要求越来越高。鉴于此&#xff0c;广东某地区的现有智慧水务平台已无法满足日益增长的智能化管理需求&#xff0c;亟待进行智慧化升级以…

工程计算与分析课程报告-Matlab

如下图所示的单自由度系统: m20kg, c30 Ns/m, and k3000 N/m. 1、应用数学、机械等理论知识推导出以下系统的数学模型&#xff1a; 其中&#xff1a; x坐标如上图所示&#xff0c;取其稳态点为零点。 M为重物质量 K为弹簧弹性系数 C为阻尼系数 F(t)为施加在重物上的外激励…

应用层协议HTTP

应用层协议HTTP 注1. HTTP协议2. 认识URL3. HTTP 协议请求与响应格式3.1.快速获取HTTP请求3.2 快速解析HTTP请求3.3 细致了解HTTP请求与响应 4. 完善Http.hpp代码&#xff0c;实现http协议4.1 http请求4.2再谈URL4.3构建http应答4.4 Content-Type属性 5.HTTP请求/响应属性5.1HT…

vscode+git解决远程分支合并冲突

1&#xff09;远程分支和远程分支不复杂情况合并 例如readme的冲突 可直接在github上解决 删到只剩下 #supergenius002 合并冲突测试1/合并测试冲突1合并测试冲突2/合并测试冲突2就行 《《《/》》》也要删掉 2&#xff09;但如果是复杂的冲突&#xff0c;让我们回到vscod…

glsl shader中实现canvas中的createRadialGradient效果

在网上找了好久&#xff0c;也没有发现有现成用shader去实现canvas radialGradient效果的.大部分都是简单的只有一个中心圆或者通过canvas绘制渐变再作为纹理图像进行贴图&#xff0c;没有类似像canvas有内圆与外圆&#xff0c;两圆心位置不一样&#xff0c;可以用实现类似焦点…

【开发问题记录】启动某个微服务时无法连接到seata(seata启动或配置异常)

问题记录 一、问题描述1.1 问题复现1.1.1 将Linux中的部分微服务启动1.1.2 在本地启动当时出错的服务 1.2 解决思路1.2.1 Nacos中seata相关的信息1.2.2 Linux中seata相关的信息 二、问题解决2.1 seata的配置错误2.1.1 Nacos中seata的配置问题2.1.2 命名空间问题的发现 2.2 网络…

Python数值计算(12)

本篇说说Neville方法。Neville方法的基础是&#xff0c;插值多项式可以递归的生成&#xff0c;有时进行插值的目的是为了计算某个点的值&#xff0c;这个时候并不需要将拟合曲线完全求出&#xff0c;而是可以通过递归的方式进行计算&#xff0c;具体操作如下&#xff1a; 例如…

代码实践思考:ROS1和ROS2

扩展 能否借助人工智能工具将ROS1批量转为ROS2如何更高效的进行ROS学习 ROS1大量案例直接批处理用智能工具转为ROS2案例 不同版本之间的工具软件直接用智能方式进行代码升级 例如OpenCV之类&#xff0c;一些函数变化&#xff0c;直接用智能工具进行批量代码优化 机器人画圆-…

滞回比较器工作原理,应用,TINA仿真

滞回比较器 滞回比较器的主要应用是增加滞回控制&#xff0c;让其对微小的变化不那么敏感&#xff0c;增强抗干扰能力&#xff0c;避免由噪声引起的不稳定状态&#xff0c;通常用于噪声环境下的阈值检测以及信号调理。根据不同需求&#xff0c;滞回比较器还可以设计成开漏极输出…

超级智能体创造营:启动!我的情侣匹配度测试助手

零、写在前面 听说由百度文心智能体平台主办&#xff0c;万众瞩目的 超级智能体创造营 第三期启动啦&#xff01; 在本期的创造营中&#xff0c;博主开发了一款有趣的超级智能体&#xff1a;情侣匹配度测试助手。 为什么要开发它呢&#xff0c;快来听博主娓娓道来吧~ 一、超…

【通俗理解】自由意志与预测——混沌理论与预测的不可能性

【通俗理解】自由意志与预测——混沌理论与预测的不可能性 自由意志与预测的类比 你可以把自由意志比作一只难以捉摸的蝴蝶&#xff0c;它的每一次振翅都可能引发不可预测的风暴。而预测则像是一个试图捕捉这只蝴蝶的网&#xff0c;但往往因为蝴蝶的微小变动而错失目标。 自由意…

五大AI测试开源框架及使用方法介绍

AI测试框架是一套系统的测试工具和方法&#xff0c;包括测试的规范和基础代码&#xff0c;涵盖了一系列的测试思想和方法。这些框架可以帮助开发者和测试人员对AI模型进行测试&#xff0c;确保AI模型在真实世界的应用中能够达到预期的效果。接下来的内容&#xff0c;我们将介绍…

PHP苹果 V X iPhone微商i o s多分开V X语音转发密友朋友圈一键跟圈软件

苹果VX神器&#xff01;iPhone微商必备&#xff1a;ios多开、VX语音转发、密友朋友圈一键跟圈软件大揭秘&#xff01; 一、iOS多开新境界&#xff0c;工作生活两不误&#xff01; 你是不是也烦恼过&#xff0c;想要在工作号和生活号之间自由切换&#xff0c;却因为iPhone的限制…

【vue3】pinia配置(任意组件通信,集中状态管理容器)

选择式写法 一、安装pinia依赖 终端输入&#xff1a;npm install pinia 二、配置pinia 第一步&#xff1a;创建仓库&#xff0c;在src目录下创建文件夹modules和文件index.ts. 第二步&#xff1a;配置index.ts // 创建pinia大仓库 import { createPinia } from "pin…

H5+JS视频列表

源码在最后面 好像有些浏览器不适配&#xff08;可能是设置了禁用自动播放的功能&#xff09; 实现功能 视频自动无声播放鼠标置于某个视频板块之上时自动无声播放点击视频跳转视频链接 效果图&#xff08;部分 视频加载可能有点慢&#xff09; 部分功能实现原理 1.无声播放…

学习C语言第十六天(调试、)

调试 第一题 C 第二题 A 第三题 C 第四题 C 第五题 D release不可以调试 第六题 越界访问访问到了i的地址 编程题 模拟strcpy void my_strcpy(char*arr1,char*arr2) {while (*arr2){*arr1 *arr2;} } int main() {char arr1[50…

【足球走地软件】走地数据分析预测【大模型篇】走地预测软件实战分享

了解什么是走地数据&#xff1f; 走地数据分析&#xff0c;在足球赛事的上下文中&#xff0c;是一种针对正在进行中的比赛进行实时数据分析的方法。这种方法主要用于预测比赛中的某些结果或趋势&#xff0c;如总进球数、比分变化、球队表现等。 在足球走地数据分析中&#xf…

仕考网:公务员可以报考军队文职吗?

公务员可以报考军队文职考试&#xff0c;但是需要满足前提条件。 对于已经与国家、地方的用人单位建立劳动关系的社会人才&#xff0c;在获得当前用人单位的许可后才可以申请报考。 在面试过程中&#xff0c;考生必须出示一份由其用人单位出具的且加盖公章的同意报考证明。一…

C++: set容器

一、关联式容器 我们已经了解了STL中的部分容器&#xff0c;比如vector、list、deque等&#xff0c;这些容器被称为序列式容器&#xff0c;其底层为线性序列的数据结构&#xff0c;里面存储的是元素本身。 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同&#xf…