C++中的依赖注入
目录
1.概述
2.构造函数注入
3.setter方法注入
4.接口注入
5.依赖注入框架
6.依赖注入容器
7.依赖注入框架的工作原理
8.依赖注入的优势
9.总结
1.概述
依赖注入是一种设计模式,它允许我们在不直接创建对象的情况下为对象提供其依赖项;它通过将对象的依赖关系从内部实现转移到外部配置,以此来实现松耦合;这使得我们的代码更易于测试、维护和扩展。
然而,在C++中实现依赖注入(Dependency Injection, DI)通常比在一些其他语言(如Java或.NET)中更具挑战性,因为C++是一种静态类型语言,且没有内建的依赖注入框架。不过,通过一些设计模式和技术,我们可以在C++项目中实现依赖注入。
依赖注入主要有以下三种方式:
-
构造函数注入:将被依赖对象通过构造函数的参数传递依赖对象,并且在初始化对象的时候注入。
-
属性注入:通过属性(成员变量)来传递依赖对象。
-
接口注入:通过接口方法传递依赖对象。
在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.总结
依赖注入框架是一种强大的软件设计模式实现工具,它能够帮助开发者降低代码的耦合度,提高代码的可测试性、可维护性和可扩展性。通过外部配置或代码逻辑将依赖项注入到目标对象中,依赖注入框架使得对象的创建、配置和生命周期管理变得更加灵活和高效。
推荐阅读:
面向对象设计之依赖反转原则
相关文章:
C++中的依赖注入
目录 1.概述 2.构造函数注入 3.setter方法注入 4.接口注入 5.依赖注入框架 6.依赖注入容器 7.依赖注入框架的工作原理 8.依赖注入的优势 9.总结 1.概述 依赖注入是一种设计模式,它允许我们在不直接创建对象的情况下为对象提供其依赖项;它通过将…...
CSS平面转换-平移
平面转换-平移 属性 transform: translate(X轴移动距离, Y轴移动距离); 取值 像素单位取值百分比(参照盒子自身尺寸计算结果)正负均可 技巧translate()只写一个值表示只沿着X轴移动单独设置X或Y轴距离:translateX()或translateY() 代码 …...
Linux-3:Shell编程——基础语法(0-50%)
目录 前言 一、变量 1.定义变量 2.使用变量 3.修改变量 4.将命令的结果赋值给变量 5.只读变量 6.删除变量 二、传递参数 三、字符串 1.字符串举例 2.统计字符串长度 3.字符串拼接 4.截取字符串 总结 前言 Shell是一种程序设计语言。作为命令语言,它…...
C++ --> string类模拟实现(附源码)
欢迎来到我的Blog,点击关注哦💕 前言: C中STL扮演着极其重要的角色,学习C重中之重的就是学习STL,虽然string不作为containers的其中一员,但是也是值得学习的le类。下面就进行string的模拟实现 string的模拟…...
基于PHP+MySQL组合开发的微信活动投票小程序源码系统 带完整的安装代码包以及搭建部署教程
系统概述 在当今数字化时代,微信作为社交媒体的巨头,为企业和个人提供了丰富的互动营销平台。其中,投票活动作为一种有效的用户参与和互动方式,被广泛应用于各种场景。为了满足这一需求,我们推出了一款基于PHPMySQL组…...
利用Arcgis设置分式标注(分子分母标注)
因工作需要,需要设置分式标注,下面详细介绍下如何利用arcgis 设置分式标注,以下操作以供参考,如有疑义可提出。 一、准备工作 软件:arcmap 示例数据:行政区shp矢量图 二、操作步骤 1.添加数据 将行政区sh…...
大麦网抢票攻略:使用Python Selenium实现
随着互联网技术的发展,在线购票已成为人们获取演出、比赛等活动门票的主要方式。然而,面对热门活动,门票往往在开售瞬间被抢购一空。为了解决这一问题,本文将介绍如何利用Python和Selenium技术实现大麦网的自动抢票。 1. 环境准备…...
Navicat 在整个数据库中查找字符
Navicat 在整个数据库中查找字符 1.首先打开Navicat,连接目标数据库。2.选择工具选项卡,选择在数据库或模式中查找。3.查找前填入关键字信息,点击查找4.双击查找到数据,进行查看 说明:当我们知道数据库有数据的关键字,…...
Python基础—处理时间问题
一文帮助您解决99%时间处理问题...
如何选择合适的自动化测试工具!
选择合适的自动化测试工具是一个涉及多方面因素的决策过程。以下是一些关键步骤和考虑因素,帮助您做出明智的选择: 一、明确测试需求和目标 测试范围:确定需要自动化的测试类型(如单元测试、集成测试、UI测试等)和测试…...
数字图像边缘曲率计算及特殊点检测
一、曲率和数字图像边缘曲率检测常用方法简介 边缘曲率作为图像边缘特征的重要参数,不仅反映了边缘的几何形状信息,还对于图像识别、图像分割、目标跟踪等任务具有显著影响。 曲线的曲率(curvature)就是针对曲线上某个点的切线方向…...
python map
在 Python 中,如果你指的是字典(dictionary),可以使用字典的 .items() 方法来遍历键值对。Python 中没有严格意义上的 Map 类型,而是使用字典来实现类似于键值对映射的功能。 遍历字典的键值对 可以使用 for 循环和 …...
每日一练 - NFV部署应用环境
01 真题题目 NFV 常常部署在下列哪些应用环境中?(多选) A.数据中心 B.网络节点 C.用户接入侧 D.客户机/服务器 02 真题答案 ABC 03 答案解析 NFV(Network Functions Virtualization,网络功能虚拟化)是一种技术,它允许在标准的…...
031-GeoGebra中级篇-GeoGebra的布尔值
在 GeoGebra 中,布尔值和条件判断是实现动态数学模型和交互式几何图形的重要工具。布尔值,即逻辑值,只有两个可能的取值:真(True)或假(False)。通过使用布尔值,我们可以创…...
基于Debian用户安装星火商店
星火商店下载地址:https://www.spark-app.store/ 本文章我以kali linux来做示范 注:基本debian的linux包括ubuntu,mint linux,kali linux,Pop!_OS,deepin等等 1.点击下载最新版本 2.点击下载 3.点击开始下载(它会自动跳转网页) 4.选择要下载…...
《计算机网络》(第8版)课后习题答案
【1-01】 计算机网络可以向用户提供哪些服务? 解答:这道题没有现成的标准答案,因为可以从不同的角度来看“服务”。 首先要明确的是,计算机网络可以向用户提供的最重要的功能有两个:连通性和共享。所 谓连通性,就是计算机网络使上网用户之间都可以交换信息,好像这些用户…...
我们的网站被狗爬了!
大家好,我是程序员鱼皮。 世风日下,人心不古。我们的程序员面试刷题网站 《面试鸭》 才刚刚上线了一个多月,就由于过于火爆,被不少同行和小人发起网络攻击。 而且因为我们已经有 4500 多道人工整理的企业高频面试题、100 多个各…...
docker安装与container基本使用
安装 Homebrew 的 Cask 已经支持 Docker for Mac, mac用户狂喜 brew install --cask --appdir/Applications docker其他入门用法可参考 Docker Hello World- 菜鸟教程 或网上自行搜索博客学习。本文主要记录我运行go-zero-mall用到的一些注意点。当然,gonivinck项…...
掌握文本搜索的利器:深入解析 Linux grep 命令的强大功能
grep 是一个强大的命令行工具,用于在文件中搜索指定的模式(字符串或正则表达式)。它的名字来源于 "global regular expression print",常用于文本处理、日志分析等任务。以下是 grep 命令的详细介绍和常用操作: 基本用法 搜索匹配的行 grep "pattern"…...
【天机学堂】面试总结
写在前面,首先要将天机学堂包装一下,智慧教育平台》,暂时就想到这个。天机学堂文档 1.包装简历 待更新。。。...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
