0%

设计模式原则之:依赖倒置原则DIP

定义

依赖倒置原则,英文缩写DIP,全称Dependence Inversion Principle。

原始定义:High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions。

官方翻译:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。


原理

上面的定义不难理解,主要包含两次意思:

  • 高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。换言之,模块间的依赖是通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。

  • 接口和抽象类不应该依赖于实现类,而实现类依赖接口或抽象类。这一点其实不用多说,很好理解,“面向接口编程”思想正是这点的最好体现。


被“倒置”的依赖

相比传统的软件设计架构,比如我们常说的经典的三层架构,UI层依赖于BLL层,BLL层依赖于DAL层。由于每一层都是依赖于下层的实现,这样当某一层的结构发生变化时,它的上层就不得不也要发生改变,比如我们DAL里面逻辑发生了变化,可能会导致BLL和UI层都随之发生变化,这种架构是非常荒谬的!好,这个时候如果我们换一种设计思路,高层模块不直接依赖低层的实现,而是依赖于低层模块的抽象,具体表现为我们增加一个IBLL层,里面定义业务逻辑的接口,UI层依赖于IBLL层,BLL层实现IBLL里面的接口,所以具体的业务逻辑则定义在BLL里面,这个时候如果我们BLL里面的逻辑发生变化,只要接口的行为不变,上层UI里面就不用发生任何变化。

在经典的三层里面,高层模块直接依赖低层模块的实现,当我们将高层模块依赖于底层模块的抽象时,就好像依赖“倒置”了。这就是依赖倒置的由来。通过依赖倒置,可以使得架构更加稳定、更加灵活、更好应对需求变化。


依赖倒置的目的

上面说了,在三层架构里面增加一个接口层能实现依赖倒置,它的目的就是降低层与层之间的耦合,使得设计更加灵活。从这点上来说,依赖倒置原则也是“松耦合”设计的很好体现。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class IDevice
{
public:
virtual ~IDevice() {}

virtual void Login() = 0;
virtual bool Spider() = 0;

};

class DeviceMML : public IDevice
{
public:
virtual ~DeviceMML() {}

void Login()
{
std::cout << "DeviceMML Login" << std::endl;
}

bool Spider()
{
std::cout << "DeviceMML Spider" << std::endl;

return true;
}
};

class DeviceTL2 : public IDevice
{
public:
virtual ~DeviceTL2() {}

void Login()
{
std::cout << "DeviceTL2 Login" << std::endl;
}

bool Spider()
{
std::cout << "DeviceTL2 Spider" << std::endl;

return true;
}

};

class DeviceService
{
public:
explicit DeviceService(IDevice* device) : _device(device)
{
}

virtual ~DeviceService() {}

void DeviceLogin()
{
_device->Login();
}

bool DeviceSpider()
{
return _device->Spider();
}

private:
IDevice* _device;
};

int main(int argc, char const *argv[])
{
/* code */
DeviceMML deviceMML;
DeviceTL2 deviceTL2;

DeviceService ds1(&deviceMML);
ds1.DeviceLogin();
ds1.DeviceSpider();

DeviceService ds2(&deviceTL2);
ds2.DeviceLogin();
ds2.DeviceSpider();

return 0;
}

输出:

DeviceMML Login
DeviceMML Spider
DeviceTL2 Login
DeviceTL2 Spider

本文只做本人学习笔记,详情请看原文
原文地址:小话设计模式原则之:依赖倒置原则DIP