设计模式(9):桥接模式BRIDGE

桥接模式的定义

将抽象部分与它的实现部分分离,使它们都可以独立地变化。


使用场景

以下情况使用Bridge模式

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式让你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户端不产生影响,即调用者的代码不必重新编译。
  • 有大量的类要生成,这种类的继承关系印证了将对象拆分成多个部分的需求
  • 你想在多个对象之间共享实现又想对调用者隐藏细节时

结构

桥接模式结构如下
ShowImage

  • Abstraction

    – 定义抽象类的接口。

    – 维护一个指向Implementor类型对象的引用。

  • RefinedAbstraction

    – 扩充由Abstraction定义的接口。

  • Implementor

    – 定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。

  • ConcreteImplementor

    – 实现Implementor接口并定义它的具体实现。

协作

Abstraction将Client的请求转发给它的Implementor对象。


效果

  • 分离接口及其实现部分

    一个实现未必不变地绑定在一个接口上。抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。

    将Abstraction与Implementor解耦有助于降低在编译时对实现部分的依赖性,当改变一个实现类时,并不需要重新编译Abstraction类和它的客户程序。为了保证一个类库的不同版本之间的二进制兼容性,一定要有这个性质。

    另外,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。

  • 增加可扩展性

    你可以独立地对Abstraction和Implementor层次结构进行扩展。

  • 实现细节对客户透明

    你可以对客户隐藏实现细节

桥接模式实现(Implement)

案例

现在要开发一款画图工具,首先有一些形状,比如正方形、三角形、圆形,形状有各种各样的颜色,比如红色、蓝色、绿色,形状还有自己的边框,虚线或者实线的,也就是说形状有三种,颜色也有三种,边框有两种,这样的话一共有3x3x2=18种类型的形状了,如果对他们一一创建类的话十分复杂,这还不算特别多,如果再增加几种颜色或形状,类的数量就无法承受了。所以,桥接模式在这里就派上用场了。

结构

案例结构如下
ShowImage


代码实现

Shape类

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class Shape {
protected Color color;
protected Border border;
public Shape(Color color, Border border) {
this.color = color;
this.border = border;
}
abstract public void color();
abstract public void drawBorder();
}

Round类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Round extends Shape {
public Round(Color color, Border border) {
super(color, border);
}
@Override
public void drawBorder() {
System.out.println("Round drawing border...");
border.applyBorder();
}
@Override
public void color() {
System.out.println("Round coloring...");
color.applyColor();
}
}

Color类

1
2
3
public interface Color {
void applyColor();
}

Blue类

1
2
3
4
5
6
public class Blue implements Color {
@Override
public void applyColor() {
System.out.println("Blue color ready...");
}
}

Border类

1
2
3
public interface Border {
void applyBorder();
}

DottedLineBorder类

1
2
3
4
5
6
public class DottedLineBorder implements Border {
@Override
public void applyBorder() {
System.out.println("Dotted line border ready...");
}
}

画出蓝色虚线边框的圆

1
2
3
4
5
System.out.println("开始绘制...蓝色虚线边框圆形");
Round blueDottedLineRound = new Round(new Blue(), new DottedLineBorder());
blueDottedLineRound.drawBorder();
blueDottedLineRound.color();
System.out.println("-------------------Shape Completed-------------------");

总结

由例子可以看到我们在画圆的时候,可以动态的指定颜色和边框类型,并且抽象方法color()与具体颜色的实现applyColor()分离了,同样drawBorder()与具体边框类型的实现也分离了,并且对调用者隐藏了内部实现细节,调用者只需要调用color()方法和drawBorder()方法就可以了。假如还有其他的属性需要动态变化调整,甚至可以使用set方法进行设置。除此之外,扩展性也变好了,如果需要增加颜色,只需要增加实现Color的类即可。桥接模式使得系统内的抽象与实现之间的关系更加灵活,不同于Adapter模式,桥接模式在设计阶段就应该好好考虑使用,这也使得系统的扩展性更好。

参考代码

------ 本文结束 ------

版权声明


BillyYccc's blog by Billy Yuan is licensed under a Creative Commons BY-NC-SA 4.0 International License.
本文原创于BillyYccc's Blog,转载请注明原作者及出处!