设计模式-桥模式(Bridge)

问题提出

假设现在需要实现一个跨平台的聊天系统,其中会包括实现具体业务逻辑的方法(如登录、发送文字、发送图片)和与平台相关的方法(如建立连接、播放声音、显示文字、显示图片)。

1.0 版本

根据上面的需求,我们可以定义一个 Messager 的抽象类,其中包含了需要实现的所有功能的函数。代码如下:

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
87
88
89
90
91
92
93
class Messager
{
public:
virtual void Login(string username, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(string image) = 0;

virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;

virtual ~Messager() { }
};

// 平台实现 -- PC 平台
class PCMessagerBase : public Messager
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// 平台实现 -- 移动平台
class MobileMessagerBase : public Messager
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// PC 平台下的业务逻辑
class PCMessager : public PCMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
PCMessagerBase::Connect();
}
virtual void SendMessage(string message) {
//......
PCMessagerBase::WriteText();
}
virtual void SendPicture(string image) {
//......
PCMessagerBase::DrawShape();
}
};

// 移动平台下的业务逻辑
class MobileMessager : public MobileMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
MobileMessagerBase::Connect();
}
virtual void SendMessage(string message) {
//......
MobileMessagerBase::WriteText();
}
virtual void SendPicture(string image) {
//......
MobileMessagerBase::DrawShape();
}
};

int main()
{
Messager * messager = new MobileMessager;
delete messager;
return 0;
}

这样算是暂时满足了需求,但很明显可以看出问题,PC 平台和 Mobile 的业务逻辑并不存在太大的区别,但我们却用了两个类来分别实现这两个类似的功能,也就是说,每增加一个新的平台,不止要重新考虑平台相关的代码,就连业务逻辑代码也不得不新建一个类来实现。

如果待实现的平台有 n 个,需要实现的类的个数为 (2n + 1) 个。如果这样还是可以忍耐的话,那下面的需求变化就会导致巨大的灾难。

2.0 版本

新的需求来了,现在要为每个平台分成精简版和完整版两个版本发布,它们之间不同的也是业务逻辑,可以写出下面的代码。

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class Messager
{
public:
virtual void Login(string username, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(string image) = 0;

virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;

virtual ~Messager() {

}
};

// 平台实现 -- PC 平台
class PCMessagerBase : public Messager
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// 平台实现 -- Mobile 平台
class MobileMessagerBase : public Messager
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// PC 平台精简版
class PCMessagerLite : public PCMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
PCMessagerBase::Connect();
}
virtual void SendMessage(string message) {
//......
PCMessagerBase::WriteText();
}
virtual void SendPicture(string image) {
//......
PCMessagerBase::DrawShape();
}
};

// PC 平台完整版
class PCMessagerPerfect : public PCMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
PCMessagerBase::Connect();
PCMessagerBase::DrawShape();
}
virtual void SendMessage(string message) {
//......
PCMessagerBase::WriteText();
PCMessagerBase::PlaySound();
}
virtual void SendPicture(string image) {
//......
PCMessagerBase::DrawShape();
PCMessagerBase::PlaySound();
}
};

// Mobile 平台精简版
class MobileMessagerLite : public MobileMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
MobileMessagerBase::Connect();
}
virtual void SendMessage(string message) {
//......
MobileMessagerBase::WriteText();
}
virtual void SendPicture(string image) {
//......
MobileMessagerBase::DrawShape();
}
};

// Mobile 平台完整版
class MobileMessagerPerfect : public MobileMessagerBase
{
public:
virtual void Login(string username, string password) {
//......
MobileMessagerBase::Connect();
MobileMessagerBase::DrawShape();
}
virtual void SendMessage(string message) {
//......
MobileMessagerBase::WriteText();
MobileMessagerBase::PlaySound();
}
virtual void SendPicture(string image) {
//......
MobileMessagerBase::DrawShape();
MobileMessagerBase::PlaySound();
}
};

int main()
{
Messager * messager = new MobileMessagerLite;
delete messager;
}

代码的类图如下:

test2

现在,灾难发生了,上面的代码仅有两个平台,两个版本,最终需要实现 1+2+2×2 = 7 个类,如果平台和版本的数量继续增加,当有 n 个平台,每个平台需要 m 个版本时,需要实现的类的个数为 1+n+n×m 个,这时候就需要对代码进行重构了。

3.0 版本

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
class MessagerImp;
// 业务逻辑
class Messager
{
protected:
MessagerImp *messagerImp;
public:
Messager(MessagerImp *mImp) : messagerImp(mImp) {

}
virtual void Login(string username, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(string image) = 0;

virtual ~Messager() {

}
};
// 平台实现
class MessagerImp
{
public:
virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;

virtual ~MessagerImp() {

}
};

// 平台实现 -- PC 平台
class PCMessagerImp : public MessagerImp
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// 平台实现 -- Mobile 平台
class MobileMessagerImp : public MessagerImp
{
public:
virtual void PlaySound() {
//......
}
virtual void DrawShape() {
//......
}
virtual void WriteText() {
//......
}
virtual void Connect() {
//......
}
};

// 精简版
class MessagerLite : public Messager
{
public:
MessagerLite(MessagerImp *mImp) : Messager(mImp) {}
virtual void Login(string username, string password) {
//......
messagerImp->Connect();
}
virtual void SendMessage(string message) {
//......
messagerImp->WriteText();
}
virtual void SendPicture(string image) {
//......
messagerImp->DrawShape();
}
};

// 完整版
class MessagerPerfect : public Messager
{
public:
MessagerPerfect(MessagerImp *mImp) : Messager(mImp) {}
virtual void Login(string username, string password) {
//......
messagerImp->Connect();
messagerImp->DrawShape();
}
virtual void SendMessage(string message) {
//......
messagerImp->WriteText();
messagerImp->PlaySound();
}
virtual void SendPicture(string image) {
//......
messagerImp->DrawShape();
messagerImp->PlaySound();
}
};

int main()
{
MessagerImp *mImp = new PCMessagerImp;
Messager *msg = new MessagerLite(mImp);

delete msg;
delete mImp;
return 0;
}

这边是用桥模式实现的方案,其类层次结构图如下:

test3

总结

bridge