c++中的依赖注入(Dependency Injection)是什么 如何降低代码耦合度【设计原则】

12次阅读

依赖注入是通过外部传入依赖对象来解耦模块的设计方式,核心是控制反转,常用构造函数注入,配合抽象接口(如databaseInterface)和智能指针实现松耦合、易测试。

c++中的依赖注入(Dependency Injection)是什么 如何降低代码耦合度【设计原则】

依赖注入是一种让类不自己创建依赖对象,而是由外部把依赖“送进来”的设计方式。它不解决具体功能问题,而是调整代码结构,让模块之间关系更松散、更易替换、更易测试。

依赖注入的核心是“控制反转”

传统写法里,一个类自己 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。

text=ZqhQzanResources