23种设计模式-桥接模式
Bridge模式 桥接模式
Intent/目的
将一个抽象与其实现解耦,使得两者可以独立变化
Also Known As
Handle/Body
Motivation/动机
当一个抽象可以有几种可能的实现时,通常的做法是使用继承。抽象类定义了抽象的操作,而具体的子类以不同的方式实现它。但是,这种方法并不总是足够灵活的。继承将实现和抽象永久地绑定在一起,这使得难以独立地修改、扩展和重用抽象和实现。
考虑一个用户界面工具包中可移植窗口抽象的实现。这个抽象应该使我们能够编写能在X Window系统和IBM的Presentation Manager(PM)上工作的应用程序,例如。使用继承,我们可以定义一个抽象类Window
和子类XWindow
和PMWindow
,它们为不同的平台实现了Window
接口。但是这种方法有两个缺点
- 扩展窗口抽象以涵盖不同类型的窗口或新平台是不方便的。想象一个
Window
的Icon Window
子类,它专门为图标定制了Window
抽象。为了支持两个平台的图标窗口,我们必须实现两个新类,XIconWindow
和PMIconWindow
。更糟糕的是,我们必须为每一种窗口类型定义两个类。支持第三个平台需要为每一种窗口类型定义另一个新的Window
子类。
- 这使得客户端代码依赖于特定的平台。每当客户端创建一个窗口时,它实例化一个具体的类,具有特定的实现。例如,创建一个
XWindow
对象将Window
抽象绑定到XWindow
实现,这使得客户端代码依赖于XWindow
实现。这反过来使得将客户端代码移植到其他平台变得更加困难。
客户端应该能够创建窗口而不必承诺使用具体的实现。只有窗口的实现应该依赖于应用程序运行的平台。因此,客户端代码应该实例化窗口而不提及特定的平台。
桥接模式通过将窗口抽象及其实现放置在不同的类层次结构中来解决这些问题。窗口接口(Window
、IconWindow
、TransientWindow
)有一个类层次结构,而专门针对平台的窗口实现则有另一个类层次结构,以WindowImp
为其根。例如,XWindowImp
子类提供了基于X窗口系统的实现
所有对Window
子类的操作都是根据WindowImp
接口中的抽象操作来实现的。这样可以将窗口抽象与各种平台特定的实现解耦。我们将Window
和WindowImp
之间的关系称为桥接(bridge),因为它桥接了抽象和实现,使它们可以独立变化。
Applicability/应用场景
- 您想要避免在抽象和其实现之间建立永久绑定。例如,在运行时必须选择或切换实现时可能会出现这种情况。
- 抽象和它们的实现都应该可以通过子类化进行扩展。在这种情况下,桥接模式可以让您将不同的抽象和实现组合起来,并且可以独立扩展它们。
- 对抽象的实现进行更改不应该对客户端产生影响;也就是说,客户端的代码不应该需要重新编译。
- 您希望完全将抽象的实现从客户端完全隐藏。在C++中,类的表示在类接口中是可见的。
- 您拥有类似于第一张图中所示的类的激增。这样的类层次结构表明需要将对象拆分为两部分。Rumbaugh使用术语“嵌套概括”来指代这样的类层次结构。
- 您想要在多个对象之间共享实现(可能使用引用计数),并且客户端应该对此事实保持隐藏。一个简单的例子是Coplien的String类,在该类中,多个对象可以共享相同的字符串表示(StringRep)。
Structure/结构
Participants/角色
- Abstraction (Window)
- 定义抽象的接口.
- 维护
Implementor
对象的引用.
- RefinedAbstraction (IconWindow)
- 扩展Abstraction接口.
- Implementor (Windowlmp)
- 定义了实现类的接口。这个接口不必与抽象类的接口完全对应;事实上,这两个接口可以是非常不同的。通常,
Implementor
接口仅提供原始操作,而抽象类则基于这些原始操作定义更高级别的操作
- 定义了实现类的接口。这个接口不必与抽象类的接口完全对应;事实上,这两个接口可以是非常不同的。通常,
- Concretelmplementor (XWindowImp, PMWindowImp)
- 实现
Implementor
接口,并定义具体的操作
- 实现
Consequences/总结
- 解耦接口和实现。实现不会永久绑定到一个接口上。抽象的实现可以在运行时配置。甚至对象在运行时也可以更改其实现。
解耦抽象和实现还消除了对实现的编译时依赖。更改实现类不需要重新编译抽象类及其客户端。当您必须确保不同版本的类库之间的二进制兼容性时,这个属性是至关重要的。
此外,这种解耦鼓励分层,可以导致更好结构化的系统。系统的高层部分只需了解抽象和实现
提高了可扩展性。您可以独立扩展抽象和实现的层次结构。
隐藏实现细节不对客户端可见。您可以屏蔽客户端对实现细节的了解,例如实现者对象的共享以及伴随的引用计数机制(如果有的话)。
Related Patterns/相关的模式
一个抽象工厂(Abstract Factory)可以创建和配置特定的桥接(Bridge)。
适配器(Adapter)模式旨在使不相关的类一起工作。通常在系统设计完成后应用。另一方面,桥接模式在设计中提前使用,以便让抽象和实现独立变化。