定义
桥接模式的目的是使得程序的抽象部分和实现部分相分离,使得相互间独立而不再相互依赖,使得抽象部分和实现部分的修改不至于引起对方的修改。
抽象部分抽象出供客户端直接使用的接口,而实现部分定义了抽象部分需要使用的接口,当抽象部分的实例引用了实现部分的接口的时候,我们所谓的桥接也就形成了。桥接是通过实现部分的引用,把抽象接口和实现部分的接口桥接起来,这就是桥接的来源。其原理图如下所示:
Abstraction定义了直接供客户端使用的接口,同时引用了Implementor的对象,而其中Implementor定义了实现部分的接口,这些接口是供抽象部分使用的。是的,通过桥接模式,实现部分的接口没有必要和抽象部分的接口一致,因此实现了抽象部分和实现部分的分离。当客户端向抽象部分的对象发送operationImp消息的时候,方法operationImp会向实现部分的引用imp发送消息operationImp,最后把消息传送到实现部分的具体对象。
因此,如果你想为实现部分新增另外一种实现方式,你只需要是新增的类实现Implementor定义的接口并且实现自定义的接口操作,最重要的是,该操作不会对抽象部分有任何的影响,抽象部分仍然可以在不知情的情况下继续正常工作。同样,如果你修改抽象部分,实现部分也是不需要跟着修改的,这就是桥接模式的魅力所在,完全是的抽象部分和实现部分独立起来。可以再来看看桥接模式的定义:
桥接模式使用场景
- 当一个对象有多个变化因素的时候,通过抽象这些变化因素,将依赖具体实现,修改为依赖抽象。
- 当某个变化因素在多个对象中共享时。我们可以抽象出这个变化因素,然后实现这些不同的变化因素。
- 当我们期望一个对象的多个变化因素可以动态的变化,而且不影响客户的程序的使用时。
代码示例
本例是通过创建一个游戏模拟器来演示桥接设计模式的使用。假如要使得我们的游戏模拟器支持小霸王和街机游戏,我们都知道,游戏是通过游戏手柄控制游戏的,而街机是使用游戏棒(街机没玩过,不知是否叫这个名字),所以游戏的控制方式是不同的。如果我们的模拟器要支持这两种操作方式,那么按照正常方式就需要给每一种控制方式定义一个控制类,这样就会导致大量的抽象类的子类,造成冗余和高度耦合。或许我们该换种方式,比如桥接模式,我们知道不同的游戏控制虽然控制方式不一样,但是游戏控制命令基本相同,都有上下左右、开始、等相似的功能,所以我们抽象出一个供客户端直接使用的命令类,然后再抽象出一个实现类,而所有的控制方式实现抽象出来的实现类接口即可,每个具体类都能自定义操作方式。其原理图如下所示:
总结
当我们希望抽象部分和实现部分实现低耦合的情况时的时候,我们就该考虑是否使用桥接模式了。当然,如何区别是否需要使得抽象部分和实现部分相分离,那就需要靠我们的机智了。