一、目的
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
二、背景
现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系:
我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。
试想,在一个有多种可能会变化的维度的系统中,用继承方式会造成类爆炸,扩展起来不灵活。每次在一个维度上新增一个具体实现都要增加多个子类。为了更加灵活的设计系统,我们此时可以考虑使用桥接模式。
三、桥接模式要解决的问题
将抽象部分与它的实现部分分离,使他们都可以独立地变化。“将抽象部分与它的实现部分分离”指实现系统可能有多个角度分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
讲一下我自己的理解。比如有一个通话软件,它可以支持语音聊天和视频聊天,语音聊天和视频聊天的整体流程是一致的,即呼叫、聊天、关闭,我们可以定义聊天的抽象流程;
语音聊天和视频聊天的细节不同,因此我们定义语言聊天和视频聊天的具体类,在具体类中调用操作系统提供的细粒度接口来实现聊天功能:
1)语音聊天中调用系统的开启连接实现聊天软件的呼叫功能,随后调用传输语音数据进行语音聊天,最后调用系统的断开连接实现软件的关闭聊天;
2)语音聊天中我们需要调用系统的开启连接和开启相机来开始视频聊天,随后传输语音数据和图像数据进行视频聊天,最后调用系统的断开连接和关闭相机来关闭视频聊天;
为了让我们的软件为更多人服务,我们需要开发Android和IOS两个版本,此时我们在聊天功能中调用不同操作系统的连接、开启相机、传送数据、关闭相机、断开连接。
为了让聊天软件的聊天功能和不同的操作系统解耦,我们将创建OS接口,用于抽象不同操作系统提供的连接、开启相机、传送数据、关闭相机、断开连接等细粒度接口,然后AndroidOs和IOS两个子类去分别实现不同操作系统的具体细节。
我们将聊天软件的抽象和它的实现部分分别放在独立的类层次结构中。其中一个层次结构针对聊天软件(语音聊天和视频聊天),这个类层次的抽象是Call;另一个独立的类层次结构针对平台相关的细粒度接口(包括Android和IOS),这个类层次的抽象是OS;而Call的子类的所有关于操作系统的操作都是通过接口OS实现的。这就将聊天软件的抽象和平台相关的实现部分分离开来。此时,我们将Call和OS之间的关系称为桥接,因为它在抽象类与它的实现之间起到桥梁的作用,使他们可以独立地变化。
四、UML类图
五、参与类的职责
1.Abstract:定义抽象类的接口;维护一个指向Implementor类型对象的引用;
2.RefinedAbstraction:扩充由Abstraction定义的接口;
3.Implementor:定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;Implementor仅提供基本操作,Abstraction则着重定义基于这些基本操作的较高层次的操作;
4.ConcreteImplementor:实现Implementor接口并定义它的具体实现;
六、协作方式
Abstraction将Client的请求转发给它的Implementor对象。RefinedAbstraction实现Abstraction中定义的抽象部分,ConcreteImplementor则实现Implementor中定义的抽象部分,最终RefinedAbstraction和ConcreteImplementor独立实现细节,Abstraction和Implementor则作为稳定的抽象部分。
七、达到的效果
1)分离接口及实现部分:接口与实现分离有助于分层,产生更好的结构化系统,系统的高层次部分仅需要关注抽象接口即可。
2)提高可扩展性:在一个维度有变化,不需要调整另外一个维度的任何代码;可以独立地对多个维度进行扩展。
3)实现细节对客户透明:客户不需要关注任何实现细节,仅仅需要关注抽象类逻辑。
八、代码示例