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.包装简历 待更新。。。...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...
