描述
定义
将抽象部分与它的实现部分分离,使它们都可以独立地变化。桥接模式(Bridge Pattern)又称为柄体(Handle/Body)模式。
类型
对象结构型模式
UML类图
时序图
简介
当一个抽象可能有多个实现时,通常用继承来协调它们。抽象类定义对该抽象的接口,而具体的子类则用不同方式加以实现。但是此方法有时不够灵活。继承机制将抽象部分与它的实现部分固定在一起,使得难以对抽象部分和实现部分独立地进行修改、扩充和重用。Bridge模式将抽象和它的实现部分分别放在独立的类层次结构中,使它们可以独立地变化。
实现
主要角色
- Abstraction:抽象类接口,维护一个Implementor类型对象的引用。
- RefinedAbstraction:扩充抽象类,扩充由Abstraction定义的接口。
- Implementor:实现类接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。
- ConcreteImplementor:具体实现类,实现Implementor接口并定义它的具体实现。
示例
以评价一个地方红烧肉的口味为例,这里有两个维度的变化:地域和餐馆品牌。
-
Abstraction:城市抽象类,包含了一个Restaurant(Implementor)引用。
public abstract class AbstractCityArea { protected Restaurant restaurant; public AbstractCityArea(Restaurant restaurant) { this.restaurant = restaurant; } public abstract void commentTaste(); }
-
Implementor: 实现类接口,餐馆的接口。
interface Restaurant { String taste(); }
-
ConcreteImplementor:具体实现类,具体的餐馆:小南国和外婆家。
public class XiaoNanGuo implements Restaurant { @Override public String taste() { return "红烧肉比较好吃"; } } public class WaiPojia implements Restaurant { @Override public String taste() { return "红烧肉比较一般"; } }
-
RefinedAbstraction:扩充抽象类,具体的城市类。
public class NanjingRestaurant extends AbstractCityArea { public NanjingRestaurant(Restaurant restaurant) { super(restaurant); } @Override public void commentTaste() { System.out.println("南京的" + super.restaurant.taste()); } } public class ShanghaiRestaurant extends AbstractCityArea { public ShanghaiRestaurant(Restaurant restaurant) { super(restaurant); } @Override public void commentTaste() { System.out.println("上海的" + super.restaurant.taste()); } }
-
Client:客户类
public class Client { public static void main(String[] args) { // 去了上海要吃红烧肉,正好他去了小南国,这时候他要评价了 Restaurant rest1 = new XiaoNanGuo(); AbstractCityArea sr1 = new ShanghaiRestaurant(rest1); sr1.commentTaste(); // 又来到南京,去外婆家去吃红烧肉,吃完又要评价了 Restaurant rest2 = new WaiPojia(); AbstractCityArea sr2 = new NanjingRestaurant(rest2); sr2.commentTaste(); } }
适用场景
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
- 抽象化角色和具体化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个具体化子类的对象进行组合,即系统需要对抽象化角色和具体化角色进行动态耦合。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
优点
- 分离接口及其实现部分。一个实现未必不变地绑定在一个接口上。抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。
- 桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法。
- 提高可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
- 实现细节对客户透明。可以对客户隐藏实现细节。
缺点
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
相关模式
- Abstract Factory模式可以用来创建和配置一个特定的Bridge模式。通常用于Abstraction只能使用特定的Implementor的情况。在这种情况下, 可以用Abstract Factory封装Client代码中建立Abstraction和Implementor连接的部分。
- Adapter模式用来帮助无关的类协同工作,它通常在系统设计完成后才会被使用。然而,Bridge模式则是在系统开始时就被使用,它使得抽象接口和实现部分可以独立进行改变。
- Builder可以和Bridge一起使用,Director作为Abstraction多个Builder作为Implementor。