FANGYEFENG

Apr 30, 2024

boost::di 依赖注入

什么是依赖注入?

我的理解是这样的,你有一个类,类里面一个成员,你需要这个成员的功能,那你肯定要先初始化,初始化就有两种方式,一种是类内初始化,一种通过取构造函数的参数来初始化,后一种就是依赖注入了,特别是在参数是基类的时候,参数具体是哪个类不是由你来决定的,由调用这个类的使用者来确定。

boost::di 官方示例
1
2
3
4
5
6
7
8
9
10
11
12
13
class Model { // Better
public:
explicit Model(std::unique_ptr<Service> service)
: service(std::move(service))
{ }

void update() {
service->do_something_with_board();
}

private:
std::unique_ptr<Service> service;
};

上面的代码就是依赖注入,Service是一个抽象类,有纯虚函数 do_something_with_board,下面可能有 DogServiceCatService等等,构造函数的调用使用的具体类你是看不到的,这种写法的最大好处就是降低了耦合度,遵从SOLID原则。
但是有这么一个情况,当项目较大时,可能有好几个类甚至好几十个类之间是一种依赖传递的关系,这种情况下,构建的顺序和参数需要牢记,写起来较为麻烦,比如下面的代码

boost::di 官方示例
1
2
3
4
5
6
7
8
9
10
int main() {
logger logger_;
renderer renderer_;
view view_{renderer_, logger_};
model model_{logger_};
controller controller_{model_, view_, logger_};
user user_{logger_};
app app_{controller_, user_};
return 0;
}

看起来就有点恐怖是不是,有了boost::di这个库,就不需要自己写这些了,换成以下写法

boost::di 官方示例
1
2
3
4
5
6
7
8
9
10
11
12
int main() {
const auto injector = di::make_injector(
di::bind<logger>.to<logger>(),
di::bind<renderer>.to<renderer>(),
di::bind<view>.to<view>(),
di::bind<model>.to<model>(),
di::bind<controller>.to<controller>(),
di::bind<user>.to<user>(),
di::bind<app>.to<app>()
);
injector.create<app>();
}

可以看到使用boost::di有一个好处,你不需要关注某一个类构造函数有几个参数和参数的顺序,这些di都帮你做了。

https://boost-ext.github.io/di/

OLDER > < NEWER