控制反转是将对象创建权交给外部容器,依赖注入通过构造函数传入依赖,C++可用模板与map实现简易DI容器,支持接口绑定与自动解析,解耦代码,提升可维护性。
在C++中实现一个简单的依赖注入(Dependency Injection, DI)容器,核心目标是解耦对象的创建和使用,将控制权交给外部容器,这正是控制反转(Inversion of Control, IoC)的核心思想。我们不需要复杂的框架,通过模板和工厂模式就能实现基本功能。
控制反转是指程序的控制流程不再由代码内部决定,而是交由外部容器管理。比如:以前是类自己new依赖对象,现在是由容器传入。
依赖注入是IoC的一种实现方式,即把类所依赖的对象通过构造函数、函数参数等方式“注入”进来,而不是在类内部直接创建。
举个例子:假设有一个Service类依赖Logger,传统写法是在Service里直接创建Logger实例,导致两者紧耦合。而用DI后,Service只声明需要一个Logger,具体哪个Logger由容器在运行时决定并注入。
我们可以用C++模板和std::function实现一个能注册类型并自动构建对象的容器。
关键思路:
代码示例如下:
#include
定义接口和实现:
struct ILogger {
virtual void log(const std::string& msg) = 0;
virtual ~ILogger() = default;
};
struct ConsoleLogger : ILogger {
void log(const std::string& msg) override {
std::cout << "[LOG] " << msg << std::endl;
}
};
struct FileLogger : ILogger {
void log(const std::string& msg) override {
std::cout << "[FILE] " << msg << std::endl; // 简化模拟
}
};
struct MyService {
std::shared_ptr logger;
MyService(std::shared_ptr l) : logger(l) {}
void doWork() {
logger->log("Doing work...");
}
};
主函数中使用容器:
int main() {
Container container;
container.Register(); // 绑定接口到实现
container.Register(); // 自注册
auto service = container.Resolve();
if (service) {
service->doWork();
}
return 0;
}
输出结果:
[LOG] Doing work...
只需修改Register语句,就能切换成FileLogger,无需改动Service代码。
上面的例子中,MyService虽然用了依赖注入,但创建仍需手动处理。理想情况是容器能自动解析构造函数参数。
可通过以下方式增强:
简单做法:显式注册带依赖的构造:
container.Register([&]() { return std::make_shared (container.Resolve ()); });
这样就实现了层级依赖的自动组装。
基本上就这些。C++没有运行时反射,所以DI容器比J
ava/Spring简单得多,但也足够应对大多数场景。关键是理解:把“谁来创建对象”的权力交出去,就是控制反转的本质。
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
php8.4如何调用com组件_php8.4windows下com操作指南【教程】
php中self::能调用子类重写的方法吗_静态绑定与重写关系【介绍】
Windows10如何重置此电脑_Windows10电脑重置方法【步骤】
Win11怎么把图标拖到任务栏_Win11固定应用快捷方式指南【方法】
Win10如何备份驱动程序_Win10驱动备份步骤【攻略】
php打包exe如何加密代码_防反编译保护方法【技巧】
php串口通信波特率怎么选_根据硬件手册设置正确波特率【方法】
Win11怎么关闭搜索历史_Win11清除任务栏搜索记录【隐私】
MAC怎么解压RAR格式文件_MAC第三方解压工具安装与压缩包管理【教程】
php485函数执行慢怎么优化_php485性能提升小技巧【技巧】
如何使用Golang实现Web表单数据绑定_自动映射字段到结构体
Win10怎样卸载TeamViewer_Win10卸载TeamViewer步骤【教程】
Win11右键反应慢怎么办 Win11优化右键菜单加载速度【技巧】
如何使用Golang进行HTTP服务性能测试_测量吞吐量和延迟
C#怎么使用委托和事件 C# delegate与event编程方法
Win11怎么关闭通知消息_屏蔽Windows 11右下角弹窗通知设置【详解】
php8.4新语法match怎么用_php8.4match表达式替代switch【方法】
Bpmn 2.0的XML文件怎么画流程图
Python多进程教程_multiprocessing模块实战
Python函数参数高级用法_默认值与可变参数解析【教程】
Win11怎么连接投影仪_Win11多显示器投屏设置指南【步骤】
如何使用Golang实现微服务事件驱动_使用消息总线解耦服务
Win11怎么恢复出厂设置_Win11重置此电脑保留文件方法【详解】
Windows怎样关闭桌面弹窗广告_Windows关闭桌面弹窗设置【教程】
c++中explicit(bool)的用法 c++条件性explicit【C++20】
如何在 PHP 单元测试中正确模拟带方法的图像处理门面(Facade)
Win11怎么打开旧版计算器_Win11恢复传统计算器应用【详解】
如何在Golang中使用encoding/gob序列化对象_存储和传输数据
Win11文件扩展名怎么显示 Win11查看文件后缀名设置【步骤】
Win10闹钟铃声怎么自定义 Win10闹钟自定义铃声教程【方法】
PHP怎么接收URL中的锚点参数_获取#后面参数值的技巧【详解】
Windows10电脑怎么设置自动连接WiFi_Win10无线网络属性勾选
Mac如何解压zip和rar文件?(推荐免费工具)
如何使用Golang实现错误包装与传递_Golangfmt.Errorf%w使用实践
Python文件操作优化_大文件与流处理解析【教程】
如何在Golang中引入测试模块_Golang测试包导入与使用实践
Go 语言标准库为何不提供泛型 Contains 方法?
使用类变量定义字符串常量时如何实现类型安全的 Literal 注解
Win11怎么制作U盘启动盘_Win11原版系统安装盘制作【详解】
php订单日志怎么在swoole写_php协程swoole写订单日志教程【教程】
Go 中 defer 在 goroutine 内部不生效的原因与执行时机详解
C++ STL算法库怎么用?C++常用算法函数(sort, find)教程【效率提升】
c++ std::atomic如何保证原子性 c++ CAS操作原理【底层】
php条件判断怎么写_ifelse和switchcase的使用区别【对比】
Windows如何设置登录时的欢迎屏幕背景?(锁屏界面)
如何正确访问 Laravel 模型或对象的属性而非调用不存在的方法
Win11怎么清理C盘OneDrive缓存_Win11清理OneDrive缓存技巧【方法】
Python项目回滚策略_发布安全说明【指导】
Ajax提交表单PHP怎么接收_处理Ajax发送的表单数据技巧【指南】
如何使用Golang搭建Web开发环境_快速启动HTTP服务
2025-12-05
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。