C++中的依赖注入

目录

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.mzph.cn/news/876934.shtml

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

相关文章

云仓技术带来的物流变革影响

1、实时可视性&#xff1a; 云仓技术使物流公司能够实时跟踪和监控货物在供应链中的位置和状态。这种实时可视性提供了更好的货物追踪和管理能力&#xff0c;同时也提高了客户服务的质量。 ———————————————————— 2、仓储优化&#xff1a; 云仓技术可以…

从0开始搭建vue + flask 旅游景点数据分析系统(四):编写前端首页【数据驾驶舱】

本期我们编写数据驾驶舱页面(Dashboard)这个页面。主要任务是引入echarts 组件编写数据驾驶舱页面。 视频教程后续会更新在我的B站&#xff1a;https://space.bilibili.com/1583208775?spm_id_from666.25.0.0 推荐从教程第一集开始从零开始学习&#xff1a;https://blog.csdn…

实验室责任人员管理保障实训系统安全

在智慧校园的实训管理生态中&#xff0c;实验室责任人员的角色犹如精密机器中的关键齿轮&#xff0c;他们不仅是实验室安全与高效运转的守护者&#xff0c;更是实训教学质量的直接塑造者。这一角色的重要性&#xff0c;在智慧校园的数字化转型中得到了前所未有的凸显&#xff0…

Linux系统配置STM32的开发环境(代码编辑,编译,下载调试)

常见的stm32开发都是直接使用keil-MDK工具的&#xff0c;这是个集成开发环境&#xff0c;包含了代码编辑&#xff0c;编译&#xff0c;下载&#xff0c;调试&#xff0c;等功能&#xff0c;而且keil还是个图形化操作工具&#xff0c;直接可以点击图标案件就可以实现编译下载啥的…

Tableau入门|数据可视化与仪表盘搭建

原视频链接&#xff08;up:戴戴戴师兄&#xff09;&#xff0c;文章为笔者的自学笔记&#xff0c;用于复习回顾&#xff0c;原视频下方有原up整理的笔记&#xff0c;更加直观便捷。因为视频中间涉及的细节较多&#xff0c;建议一边操作&#xff0c;一边学习。 整体介绍 可视化…

set,map(java)

前言&#xff1a;要了解set和map&#xff0c;首先需要对搜索树和哈希有一定的了解&#xff0c;才能进一步深入的了解set和map。 1.搜索树 &#xff08;1&#xff09;性质&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点值都小于根节点的值。 若它的右子树不…

【单机锁】实现原理

文章目录 1.互斥锁 sync.Mutex 的实现原理&#xff1b;1.1获取策略有如下两种&#xff1a;1.2sync.Mutex的方案1.2.1具体方案如下&#xff1a;1.2.2转换的条件&#xff1a;1.2.3运行的两种模式&#xff1a;1.2.4两种模式的转换条件1.2.5唤醒标识&#xff1a; 1.3源码走读 2. sy…

猫头虎分享:PyTorch异常ModuleNotFoundError: No module named ‘torch’解决方案

&#x1f42f; 猫头虎分享&#xff1a;PyTorch异常ModuleNotFoundError: No module named ‘torch’解决方案 &#x1f4bb; 摘要 在本篇博客中&#xff0c;我们将深入探讨如何解决PyTorch中常见的“ModuleNotFoundError: No module named ‘torch’”错误。通过详细的步骤指…

差分法求解 Burgers 方程(附完整MATLAB 及 Python代码)

Burgers 方程的数值解及误差分析 引言 Burgers 方程是一个非线性偏微分方程&#xff0c;在流体力学、非线性声学和交通流理论中有广泛应用。本文将通过数值方法求解带粘性的 Burgers 方程&#xff0c;并分析其误差。 方程模型 Burgers 方程的形式为&#xff1a; u t u u …

Jmeter下载、安装、永久汉化(Windows环境)

1、JDK下载 JDK8下载地址https://www.oracle.com/java/technologies/downloads/#java8-windows JDK8的Windows的64位&#xff1a; 2、Jmeter下载 jmeter下载地址https://jmeter.apache.org/download_jmeter.cgi 3、配置环境变量 安装好后&#xff0c;把jdk和jmeter都配置到…

Docker从入门到实践教程(电子版)

前言 Docker 是个伟大的项目&#xff0c;它彻底释放了虚拟化的威力&#xff0c;极大降低了云计算资源供应的成本&#xff0c;同时让应用的 分发、测试、部署和分发都变得前所未有的高效和轻松&#xff01; 本电子书既适用于具备基础 Linux 知识的 Docker 初学者&#xff0c;也…

隧道可视化:实时监控保障行车安全

通过图扑可视化实现隧道的实时监控、数据分析及智能报警系统&#xff0c;提供全面的隧道管理和决策支持&#xff0c;提升行车安全&#xff0c;优化维护策略&#xff0c;确保交通顺畅。

【b站-湖科大教书匠】6 应用层 - 计算机网络微课堂

课程地址&#xff1a;【计算机网络微课堂&#xff08;有字幕无背景音乐版&#xff09;】 https://www.bilibili.com/video/BV1c4411d7jb/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 6 应用层 6.1 应用层概述 6.2 客户-服务器方式和对等方…

PsExec横向:IPCPTHPTT

一.IPC下的PsExec 二.PTH下的psexec&#xff08;CS操作&#xff09; 三.PTT下的psexec PsExec工具&#xff1a; psexec 是 windows 下非常好的一款远程命令行工具。psexec的使用不需要对方主机开方3389端口&#xff0c;只需要对方开启admin$共享和ipc$ (该共享默认开启&#…

Spring boot 后端向前端发送日期时间发现少了8小时

问题 数据库 后端的控制台输出 前端控制台输出 可以发现少了8小时 问题 springboot 向前端响应数据是默认 Json 格式&#xff0c;所以会有类型转换&#xff0c;springboot 就通过 Jackson 来对 data 类型数据进行转换&#xff0c;但是Jackson 类型的时区是 GMT&#xff0c;与…

Google AI非坦途

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Pytorch框架之神经网络

一、全连接神经网络的整体结构 二、全连接神经网络的单元结构 找出一组w,b使得结果最优 三、常见激活函数 四、前向传播 学习率是指训练模型时每次迭代更新模型参数的步长。 五、梯度下降法 六、反向传播计算 七、总结 1、准备数据 2、搭建模型 3、开始训练(设置学习率、…

【TS】TypeScript中的接口(Interface):对象类型的强大工具

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 TypeScript中的接口(Interface):对象类型的强大工具引言1. 接口的基本概念1.1 什…

【基于PSINS】UKF/SSUKF对比的MATLAB程序

UKF与SSUKF UKF是&#xff1a;无迹卡尔滤波 SSUKF是&#xff1a;简化超球面无迹卡尔曼滤波 UKF 相较于传统的KF算法&#xff0c;UKF能够更好地处理非线性系统&#xff0c;并且具有更高的估计精度。它适用于多种应用场景&#xff0c;如机器人定位导航、目标跟踪、信号处理等。…

【人工智能】深度剖析:Midjourney与Stable Diffusion的全面对比

文章目录 &#x1f34a;1 如何选择合适的AI绘画工具1.1 个人需求选择1.2 比较工具特点1.3 社区和资源 &#x1f34a;2 Midjourney VS Stable Diffusion&#xff1a;深度对比与剖析 2.1 使用费用对比 2.2 使用便捷性与系统兼容性对比 2.3 开源与闭源对比 2.4 图片质量对比 2.5 上…