什么是依赖注入?
我的理解是这样的,你有一个类,类里面一个成员,你需要这个成员的功能,那你肯定要先初始化,初始化就有两种方式,一种是类内初始化,一种通过取构造函数的参数来初始化,后一种就是依赖注入了,特别是在参数是基类的时候,参数具体是哪个类不是由你来决定的,由调用这个类的使用者来确定。
boost::di 官方示例1 2 3 4 5 6 7 8 9 10 11 12 13
| class Model { 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,下面可能有 DogService、CatService等等,构造函数的调用使用的具体类你是看不到的,这种写法的最大好处就是降低了耦合度,遵从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/