Design Patterns(六) Bridge

The bridge pattern applies when there is a need to avoid permanent binding between an abstraction and an implementation and when the abstraction and implementation need to vary independently. Using the bridge pattern would leave the client code unchanged with no need to recompile the code.

前言

    桥接模式,又叫桥梁模式,顾名思义,就是有座“桥”,那这座桥是什么呢?就是一条聚合线(下方UML图),比如我们下面会举的例子,手机有手机品牌和手机游戏等等,每个手机品牌都有多款游戏,那是不是二者之间就是聚合关系了,这是合成/聚合复用原则的体现,当我们发现类有多层继承时就可以考虑使用桥接模式,用聚合代替继承。 桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。

桥接模式

角色:

1) 桥接模式(Bridge模式)是指:将 实现与 抽象放在两个不同的类层次中,使两个层次可以独立改变;
2) 是一种结构型设计模式;
3) Bridge模式基于 类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(Implementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展。

桥接模式-UML图:


桥接模式-案例图:



代码:

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**
* @Auther: Arsenal
* @Date: 2020-03-13 21:31
* @Description: 桥接模式
*/
public class Bridge {
public static void main(String[] args) {

System.out.println("========Android FoldPhone========");
Phone phone1 = new FoldPhone(new Android());
phone1.open();
phone1.call();
phone1.close();
System.out.println("========Android UprightPhone========");
Phone phone2 = new UprightPhone(new Android());
phone2.open();
phone2.call();
phone2.close();
System.out.println("========Android SlidePhone========");
Phone phone3 = new SlidePhone(new Android());
phone3.open();
phone3.call();
phone3.close();
System.out.println("========Apple FoldPhone========");
Phone phone4 = new FoldPhone(new Apple());
phone4.open();
phone4.call();
phone4.close();
System.out.println("========Apple UprightPhone========");
Phone phone5 = new UprightPhone(new Apple());
phone5.open();
phone5.call();
phone5.close();
System.out.println("========Apple SlidePhone========");
Phone phone6 = new SlidePhone(new Apple());
phone6.open();
phone6.call();
phone6.close();
System.out.println("========Apple Nokia========");
Phone phone7 = new FoldPhone(new Nokia());
phone7.open();
phone7.call();
phone7.close();
System.out.println("========Nokia UprightPhone========");
Phone phone8 = new UprightPhone(new Nokia());
phone8.open();
phone8.call();
phone8.close();
System.out.println("========Nokia SlidePhone========");
Phone phone9 = new SlidePhone(new Nokia());
phone9.open();
phone9.call();
phone9.close();

}
}

interface Brand {
void open();

void close();

void call();
}

class Android implements Brand {

@Override
public void open() {
System.out.println("安卓手机开机了");
}

@Override
public void close() {
System.out.println("安卓手机关机了");
}

@Override
public void call() {
System.out.println("安卓手机打电话了");
}
}

class Apple implements Brand {

@Override
public void open() {
System.out.println("苹果手机开机了");
}

@Override
public void close() {
System.out.println("苹果手机关机了");
}

@Override
public void call() {
System.out.println("苹果手机打电话了");
}
}

class Nokia implements Brand {

@Override
public void open() {
System.out.println("诺基亚手机开机了");
}

@Override
public void close() {
System.out.println("诺基亚手机关机了");
}

@Override
public void call() {
System.out.println("诺基亚手机打电话了");
}
}

abstract class Phone {
Brand brand;

Phone(Brand brand) {
this.brand = brand;
}

void open() {
brand.open();
}

void close() {
brand.close();
}

void call() {
brand.call();
}

}

class FoldPhone extends Phone {

FoldPhone(Brand brand) {
super(brand);
}

@Override
void open() {
System.out.print("折叠的 ");
super.open();
}

@Override
void close() {
System.out.print("折叠的 ");
super.close();
}

@Override
void call() {
System.out.print("折叠的 ");
super.call();
}
}

class UprightPhone extends Phone {

UprightPhone(Brand brand) {
super(brand);
}

@Override
void open() {
System.out.print("直立的 ");
super.open();
}

@Override
void close() {
System.out.print("直立的 ");
super.close();
}

@Override
void call() {
System.out.print("直立的 ");
super.call();
}
}

class SlidePhone extends Phone {

SlidePhone(Brand brand) {
super(brand);
}

@Override
void open() {
System.out.print("滑盖的 ");
super.open();
}

@Override
void close() {
System.out.print("滑盖的 ");
super.close();
}

@Override
void call() {
System.out.print("滑盖的 ");
super.call();
}
}

总结

桥接模式的注意事项和细节:

1) 实现了抽象和实现部分的分离,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,这有助于系统进行分层设计,从而产生更好的结构化系统;
2) 对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其它的部分由具体业务来完成;
3) 桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本;
4) 桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程;
5) 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性,即需要有这样的应用场景。

桥接模式其它应用场景:

1) 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用;
2) 常见的应用场景:
  -JDBC驱动程序
  -银行转账系统
    转账分类: 网上转账,柜台转账,AMT转账
    转账用户类型:普通用户,银卡用户,金卡用户..
  -消息管理
    消息类型:即时消息,延时消息
    消息分类:手机短信,邮件消息,QQ消息…

延伸

    桥接模式
    Bridge Design Pattern
    23种设计模式之桥接模式
    桥梁模式(Bridge Pattern)
    桥接模式-Bridge Pattern
    尚硅谷Java设计模式,韩顺平图解java设计模式

Content
  1. 1. 前言
  2. 2. 桥接模式
  3. 3. 总结
  4. 4. 延伸