c++中的依赖注入(Dependency Injection)是什么 如何降低代码耦合度【设计原则】
发布时间 - 2026-01-06 00:00:00 点击率:次依赖注入是通过外部传入依赖对象来解耦模块的设计方式,核心是控制反转,常用构造函数注入,配合抽象接口(如DatabaseInterface)和智能指针实现松耦合、易测试。
依赖注入是一种让类不自己创建依赖对象,而是由外部把依赖“送进来”的设计方式。它不解决具体功能问题,而是调整代码
结构,让模块之间关系更松散、更易替换、更易测试。
依赖注入的核心是“控制反转”
传统写法里,一个类自己 new 依赖对象,比如:
class UserService {
Database db;
public:
UserService() : db("localhost") {} // 自己决定用哪个数据库
};
这样 UserService 和 Database 强绑定,换数据库就得改代码。而用依赖注入后:
class UserService {
Database& db; // 或指针/智能指针
public:
explicit UserService(Database& d) : db(d) {} // 依赖由外面传入
};
// 使用时:
Database mysql("192.168.1.100");
UserService service(mysql);
谁创建 Database、用 MySQL 还是 SQLite,都和 UserService 无关了——控制权从类内部转移到了外部调用者。
立即学习“C++免费学习笔记(深入)”;
三种常见注入方式(C++ 中常用)
- 构造函数注入:最推荐。依赖在对象创建时一次性传入,状态明确、不可变,适合必需依赖。
- Setter 注入:通过 public 成员函数设置依赖,适合可选依赖或运行时可能变更的场景(如日志输出目标)。
-
接口注入(较少见):定义注入接口(如 Injectable
),被注入类实现该接口。C++ 中因缺乏反射支持,一般不实用,多用于框架抽象层。
配合抽象接口才能真正解耦
只传具体类型(如 Database)仍不够——换数据库还得改参数类型。关键一步是依赖抽象而非实现:
class DatabaseInterface {
public:
virtual ~DatabaseInterface() = default;
virtual void connect() = 0;
virtual void query(const std::string&) = 0;
};
class MySQLDB : public DatabaseInterface { / 实现 / };
class SQLiteDB : public DatabaseInterface { / 实现 / };
class UserService {
std::unique_ptr db;
public:
explicit UserService(std::unique_ptr d)
: db(std::move(d)) {}
};
此时 UserService 只知道“能连、能查”,完全不知道底层是 MySQL 还是 SQLite。单元测试时还能轻松注入 MockDatabase。
实际降低耦合的关键细节
- 避免在类内部 new 具体实现类,所有 new 都应集中在少数“装配点”(如 main() 或工厂类)。
- 使用智能指针(std::unique_ptr / std::shared_ptr)管理生命周期,避免裸指针带来的所有权模糊。
- 依赖项尽量用 const 引用或 const 智能指针,表明只读使用,增强语义清晰度。
- 不要为了注入而注入——简单工具类(如 MathUtils)或无状态函数通常无需 DI。
# mysql
# 工具
# ai
# c++
# red
# 成员函数
# 构造函数
# const
# 指针
# 接口
# public
# 对象
# sqlite
# database
# 数据库
# 低代码
# 更易
# 是一种
# 还能
# 是由
# 三种
# 还得
# 就得
# 可选
# 只知道
# 而非
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
开心动漫网站制作软件下载,十分开心动画为何停播?
简单实现Android验证码
如何在IIS7上新建站点并设置安全权限?
怎么用AI帮你为初创公司进行市场定位分析?
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
php json中文编码为null的解决办法
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
linux top下的 minerd 木马清除方法
网站制作软件免费下载安装,有哪些免费下载的软件网站?
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
iOS UIView常见属性方法小结
微信小程序 require机制详解及实例代码
动图在线制作网站有哪些,滑动动图图集怎么做?
佛山网站制作系统,佛山企业变更地址网上办理步骤?
如何快速辨别茅台真假?关键步骤解析
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】
简单实现jsp分页
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
Python文本处理实践_日志清洗解析【指导】
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法
DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解
JavaScript常见的五种数组去重的方式
如何挑选最适合建站的高性能VPS主机?
如何快速启动建站代理加盟业务?
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
jQuery 常见小例汇总
如何在橙子建站上传落地页?操作指南详解
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
详解jQuery中的事件
edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
深圳网站制作培训,深圳哪些招聘网站比较好?
javascript读取文本节点方法小结
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
米侠浏览器网页背景异常怎么办 米侠显示修复
Laravel如何使用Blade模板引擎?(完整语法和示例)
如何在 Pandas 中基于一列条件计算另一列的分组均值
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
如何快速查询网址的建站时间与历史轨迹?
Laravel如何使用.env文件管理环境变量?(最佳实践)
Laravel如何优化应用性能?(缓存和优化命令)
如何用美橙互联一键搭建多站合一网站?
如何快速搭建安全的FTP站点?
nodejs redis 发布订阅机制封装实现方法及实例代码
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体

