C++设计模式中控制反转与依赖注入浅析
作者:吃个橙子吧
控制反转
“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程可以通过框架来控制。流程的控制权从程序员“反转”到了框架。
大白话说,就是原先直接用main函数中的代码流程,转移到了框架中去。
#include <iostream> #include <list> using namespace std; class TestCase { public: TestCase() {}; ~TestCase() {}; virtual int test() = 0; void run() { switch (test()) { case 1:cout << "1\ test() " << endl; break; case 2:cout << "2\ test() " << endl; break; default: break; } } }; class Cases : public TestCase { virtual int test() override { return 1; } }; class Dases : public TestCase { virtual int test() override { return 2; } }; class Application { public: void registers(TestCase *cases) { testCases.push_back(cases); } void runStage() { for (auto&it : testCases) { it->run(); } } private: list<TestCase*> testCases; }; int main() { std::cout << "Hello World!\n"; TestCase *case1 = new Cases(); TestCase *dase1 = new Dases(); Application app; app.registers(case1); app.registers(dase1); app.runStage(); }
依赖注入(DI)
什么是依赖注入呢?
概括就是:不通过 new() 的方式在类内部创建依赖类对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类使用。
class Message { public: virtual void send(string msg) = 0; }; class phoneMessage : public Message { public: virtual void send(string msg) override { cout << "this is phone msg : " << msg.c_str() << endl; } private: }; class NotifyIterface { public: NotifyIterface(Message *obj) { message = obj; } void sendMsg(string msg) { message->send(msg); } private: Message *message; }; class MessageSender { public: void sender(string msg) { cout << msg.c_str() << endl; } }; //非依赖注入 class Notification { public: Notification() { msgsender = new MessageSender(); } void sendMsg(string msg) { msgsender->sender(msg); } private: MessageSender *msgsender; }; //依赖注入 class Notification2 { public: Notification2(MessageSender *obj) { msgsender = obj; } void sendMsg(string msg) { msgsender->sender(msg); } private: MessageSender *msgsender; }; int main() { //非依赖注入的写法 Notification *notify = new Notification(); notify->sendMsg("this is not DI"); //依赖注入的写法,通过依赖注入的方式来将依赖的类对象传递进来,这样就提高了代码的扩展性 MessageSender *msgobj = new MessageSender(); Notification2 *notify2 = new Notification2(msgobj); notify2->sendMsg("this is DI"); //依赖注入,改为通过接口实现 Message *message = new phoneMessage(); NotifyIterface *notifyIterface = new NotifyIterface(message); notifyIterface->sendMsg(" Iphone !"); }
依赖注入框架(DI Framework)
在采用依赖注入实现的 Notification 类中,虽然我们不需要用类似 hard code 的方式,在类内部通过 new 来创建 MessageSender 对象,但是,这个创建对象、组装(或注入)对象的工作仅仅是被移动到了更上层代码而已,还是需要我们程序员自己来实现。
对象创建和依赖注入的工作,本身跟具体的业务无关,我们完全可以抽象成框架来自动完成。
实际上,现成的依赖注入框架有很多,比如 Google Guice、Java Spring、Pico Container、Butterfly Container 等。不过,如果你熟悉 Java Spring 框架,你可能会说,Spring 框架自己声称是控制反转容器(Inversion Of Control Container)。
不过这一块儿的东西先做了解,具体的实现需要自己想一想再去实现。
依赖反转原则(DIP)
高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。
所谓高层模块和低层模块的划分,简单来说就是,在调用链上,调用者属于高层,被调用者属于低层。在平时的业务代码开发中,高层模块依赖底层模块是没有任何问题的。
依赖反转原则也叫作依赖倒置原则。这条原则跟控制反转有点类似,主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。
到此这篇关于C++设计模式中控制反转与依赖注入浅析的文章就介绍到这了,更多相关C++控制反转与依赖注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!