依赖倒置原则(DIP,Dependence Inversion Principle)的定义是:高层模块不应该依赖底层模块,两者都应该依赖其抽象。抽象不应该依赖细节,即接口或抽象类不依赖于实现类。细节应该依赖抽象,即实现类不应该依赖于接口或抽象类。简单地说,就是说我们应该面向接口编程。通过抽象成接口,使各个类的实现彼此独立,实现类之间的松耦合。
在具体软件设计时,上层模块不应该依赖于底层模块,底层模块更不应该依赖上层模块,而是上层模块和底层模块都向中间靠拢,共同依赖于二者中间的抽象接口层。整个软件程序设计的依赖关系应该终止于抽象接口层,上层和底层互不关心,甚至使用什么编程语言都不关心。抽象接口层提供一个标准或者协议,它对上提供访问的接口,对下提供实现的标准,抽象接口层本身不执行任何操作,具体的功能由它的实现去完成。
举例来说,假如我们要组装一台电脑,现在要选择硬盘、内存、屏幕。那么电脑类要集成硬盘、内存、屏幕这些组件,但是我们希望电脑类和组件类之间不应该是相互依赖的关系,我们就可以直接给出一套接口,各个组件厂商只要实现这些抽象接口就可以装入我们的电脑中。
1. //各个组件的抽象类
2. class DiskInterface
3. {
4. public:
5. virtual void infomation() = 0;
6. };
7.
8. class MemoryInterface
9. {
10. public:
11. virtual void infomation() = 0;
12. };
13.
14. class ScreenInterface
15. {
16. public:
17. virtual void infomation() = 0;
18. };
电脑类定义如下:
1. class Computer
2. {
3. public:
4. Computer(DiskInterface* disk, MemoryInterface* memory, ScreenInterface* screen)
5. {
6. this->disk = disk;
7. this->memory = memory;
8. this->screen = screen;
9. }
10. public:
11. void get_information()
12. {
13. this->disk->infomation();
14. this->memory->infomation();
15. this->screen->infomation();
16. }
17. private:
18. DiskInterface* disk; //使用指针而不能使用变量
19. MemoryInterface* memory;
20. ScreenInterface* screen;
21. };
各个厂商根据组件的抽象类去实现,来入围电脑类:
1. //各厂商直接继承抽象类,来实现
2. class InterDisk : public DiskInterface
3. {
4. public:
5. virtual void infomation()
6. {
7. cout << "因特尔硬盘" << endl;
8. }
9. };
10.
11. class WDMemory : public MemoryInterface
12. {
13. public:
14. virtual void infomation()
15. {
16. cout << "西部数据的内存条" << endl;
17. }
18. };
19.
20. class HPScreen : public ScreenInterface
21. {
22. public:
23. virtual void infomation()
24. {
25. cout << "惠普的屏幕" << endl;
26. }
27. };
这样组件类和电脑类都依赖于抽象接口层,两者都向接口层靠近,这就是面向接口编程,也就是我们的依赖倒置原则。我们直接把各个组件的实现类定义对象并传到电脑类中即可
1. {
2. InterDisk* idisk = new InterDisk;
3. WDMemory* wdmem = new WDMemory;
4. HPScreen* hpscr = new HPScreen;
5. SamScreen* samscr = new SamScreen;
6.
7. Computer* c1 = new Computer(idisk, wdmem, hpscr); //使用惠普的屏幕
8. c1->get_information();
9.
10. delete c1;
11. delete samscr;
12. delete hpscr;
13. delete wdmem;
14. delete idisk;
15. }
假如后来,三星也想入围这个电脑,那么三星直接去实现屏幕的抽象类即可
1. class SamScreen : public ScreenInterface
2. {
3. public:
4. virtual void infomation()
5. {
6. cout << "三星的屏幕" << endl;
7. }
8. };
我们再直接把三星的屏幕传入电脑类即可
1. {
2. Computer* c2 = new Computer(idisk, wdmem, samscr); //使用三星屏幕
3. c2->get_information();
4. }