Bridge模式,又称为桥接模式,是一种结构型设计模式,它的核心思想是将抽象部分与它的实现部分分离,使它们都可以独立地变化。Bridge模式通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦,使得抽象和实现可以沿着各自的维度来变化。
一、Bridge模式的定义与特点
- 定义:在GOF的《设计模式》一书中,Bridge模式的定义为“将抽象部分与它的实现部分分离,使它们都可以独立地变化”。
- 特点:
- 解耦抽象和实现:Bridge模式通过组合的方式建立抽象类和实现类之间的联系,而不是通过继承,从而实现了抽象部分和实现部分的解耦。
- 提高扩展性:由于抽象部分和实现部分可以独立变化,因此可以在不修改原有系统的情况下,增加新的抽象类或实现类,从而提高系统的扩展性。
- 符合开闭原则:Bridge模式允许在不修改现有代码的情况下,通过增加新的实现类来扩展系统的功能,符合开闭原则(对扩展开放,对修改关闭)。
二、Bridge模式的结构
类图:
Bridge模式通常包含以下几个角色:
- Abstraction(抽象化角色):定义抽象类的接口,并维护一个指向实现化对象的引用。
- Refined Abstraction(修正抽象化角色):抽象化角色的子类,实现父类中的部分抽象业务方法,并通过组合关系调用实现化角色中的业务方法。
- Implementor(实现化角色):定义实现化角色的接口,该接口不一定要与抽象化角色的接口完全一致,事实上,这两个接口可以非常不同。实现化角色一般是提供具体的业务实现。
- ConcreteImplementor(具体实现化角色):实现化角色的具体实现。
三、Bridge模式的使用场景
- 当一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要进行扩展时,可以考虑使用Bridge模式。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,Bridge模式尤为适用。
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过Bridge模式可以使它们在抽象层建立一个关联关系。
四、Bridge模式的优缺点
- 优点:
- 分离抽象部分及其具体实现部分,提高了系统的可扩展性。
- 符合开闭原则,可动态的切换实现。
- 符合合成复用原则,实现细节对客户端透明,可以对用户隐藏实现细节。
- 缺点:
- 增加了系统的理解与设计难度,需要正确地识别出系统中两个独立变化的维度。
- 在系统前期设计阶段,如果未能准确识别出独立变化的维度,可能会导致设计上的缺陷。
五、Bridge模式的例子
以JDBC为例,JDBC为所有的关系型数据库提供一个通用的界面,通过提供一个抽象层(如Connection、Statement等接口),使得应用程序可以独立于具体的数据库实现。而具体的数据库实现(如MySQL、Oracle等)则通过各自的数据库驱动来提供。这样,当应用程序需要在不同的数据库之间切换时,只需要更换数据库驱动即可,而无需修改应用程序的代码。这就是Bridge模式在JDBC中的一个典型应用。
以下是一个简单的Java示例,展示了如何实现桥接模式:
// 实现化角色接口 interface DrawAPI { void drawCircle(int radius, int x, int y); } // 具体实现化角色 class RedCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", " + y + "]"); } } class GreenCircle implements DrawAPI { @Override public void drawCircle(int radius, int x, int y) { System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", " + y + "]"); } } // 抽象化角色 abstract class Shape { protected DrawAPI drawAPI; // 构造函数,传入实现化角色 protected Shape(DrawAPI drawAPI) { this.drawAPI = drawAPI; } // 使用实现化角色中的方法 public abstract void draw(); } // 修正抽象化角色 class Circle extends Shape { private int x, y, radius; // 构造函数 public Circle(int x, int y, int radius, DrawAPI drawAPI) { super(drawAPI); this.x = x; this.y = y; this.radius = radius; } // 调用实现化角色的方法 @Override public void draw() { drawAPI.drawCircle(radius, x, y); } } // 测试类 public class BridgePatternDemo { public static void main(String[] args) { Shape redCircle = new Circle(100, 100, 10, new RedCircle()); Shape greenCircle = new Circle(100, 100, 10, new GreenCircle()); redCircle.draw(); greenCircle.draw(); } }
在这个例子中,DrawAPI是实现化角色的接口,它定义了一个drawCircle方法。RedCircle和GreenCircle是具体实现化角色,它们分别实现了drawCircle方法,以绘制不同颜色的圆。
Shape是抽象化角色的抽象类,它持有一个DrawAPI类型的引用,并定义了一个draw方法的抽象实现。Circle是修正抽象化角色,它继承了Shape类,并实现了draw方法,该方法通过调用drawAPI引用的drawCircle方法来绘制圆。
最后,在BridgePatternDemo类中,我们创建了红色和绿色的圆,并通过调用它们的draw方法来绘制它们。由于draw方法内部调用了drawAPI引用的方法,因此我们可以通过改变drawAPI的实例来改变圆的颜色,而无需修改Circle类的代码。这就是桥接模式带来的灵活性和可扩展性。
如果有收获,记得点赞收藏。