C++中的依赖注入容器:用于依赖注入的Fruit库

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++依赖注入容器:Fruit库概述



在现代C++开发中,管理类之间的依赖关系对于创建灵活、可测试且可维护的应用程序至关重要。依赖注入(DI)模式允许将对象的创建移出类外,而DI容器则自动化了这一过程。在C++中实现依赖注入的最佳库之一是Fruit——一个轻量级、快速且类型安全的容器,在编译阶段工作。



什么是依赖注入容器?

依赖注入容器是一种工具,负责创建和连接对象(依赖项)。类不再通过new或工厂自行创建依赖项,而是由容器从外部“注入”它们。这实现了控制反转(IoC)原则,使代码变得松散耦合。



为什么选择Fruit?

Fruit库(https://github.com/google/fruit)由Google开发,与同类库(例如Boost.DI)相比具有以下特点:

  • 编译时检查:所有连接在编译阶段进行检查,消除了因缺少依赖项而导致的运行时错误。
  • 最小开销:Fruit不使用RTTI和虚函数调用,生成高效的代码。
  • 简单易用:仅需C++14和头文件——无需宏或代码生成。
  • 组件支持:可以从可重用的模块组装依赖图。


安装

Fruit作为仅头文件库分发(仅需fruit.h)。通过vcpkg安装:

vcpkg install fruit

或者克隆仓库并包含文件include/fruit/fruit.h。



核心概念

Fruit使用三个关键元素:

  • 注入器(Injector)——创建对象的容器。
  • 组件(Component)——注册类型及其工厂的模块。
  • 注解——用于区分同一接口的不同实现。


使用示例

考虑一个经典示例:服务依赖于存储库。创建一个接口和两个实现:



// interfaces.hpp#include <fruit/fruit.h>#include <string>

class ILogger {public: virtual void log(const std::string& msg) = 0; virtual ~ILogger() = default;};

class IUserRepository {public: virtual std::string getUser(int id) = 0; virtual ~IUserRepository() = default;};


实现:

// implementations.cpp#include "interfaces.hpp"#include <iostream>

class ConsoleLogger : public ILogger {public: INJECT(ConsoleLogger()) = default; // Fruit注解用于构造函数 void log(const std::string& msg) override { std::cout << "[LOG] " << msg << std::endl; }};

class SqlRepository : public IUserRepository {public: INJECT(SqlRepository()) = default; std::string getUser(int id) override { return "User_" + std::to_string(id); }};


使用两个依赖项的服务:

// user_service.cpp#include "interfaces.hpp"

class UserService {private: ILogger* logger; IUserRepository* repo;public: INJECT(UserService(ILogger* logger, IUserRepository* repo)) : logger(logger), repo(repo) {} void processUser(int id) { auto name = repo->getUser(id); logger->log("Processing user: " + name); }};


现在组装组件

推荐