桥接模式


桥接模式

概述

桥接模式 (Bridge Pattern) 是一种结构型设计模式,它的意图是将抽象部分与具体实现部分分离,使得它们可以独立变化。这种分离的设计方案在系统内部可以灵活的进行组合,从而实现系统的扩展和优化。

桥接模式采用了“组合/聚合复用原则”,即尽量使用对象组合/聚合而不是继承,来达到代码重用的目的。

结构

桥接模式的主要组成部分有以下几个:

  • 抽象化(Abstraction)角色:它是抽象化的核心,定义了抽象化的接口和具体实现部分的关联关系。抽象化角色中管理着一个指向实现化角色的引用。
  • 扩展化(RefinedAbstraction)角色:它扩展了抽象化角色中的接口,通常需要一个具体实现化角色对象来支持它的实现。
  • 实现化(Implementor)角色:它是定义实现化角色的接口,这个接口不必和抽象化角色的接口保持一致。事实上,这两个接口可以完全不同。
  • 具体实现化(ConcreteImplementor)角色:它实现了实现化角色接口,并且具体实现化角色中实现了抽象化角色定义的接口。

下面是桥接模式的UML类图:

桥接模式UML类图

工作原理

桥接模式的工作原理很简单,就是通过将抽象化角色和具体实现化角色分离出来,使得它们可以各自独立地变化,从而达到一个灵活的组合机制,支持系统的扩展和优化。

在桥接模式中,抽象化角色一般会对外提供一些基础的操作方法,这些操作方法通常会依赖于具体实现化角色。而具体实现化角色则是实现了一个完整的具体细节操作。抽象化角色持有一个指向具体实现化角色的引用,并将该引用暴露给外界,以便实现具体操作。这样,在系统运行过程中,具体实现化角色的实例可以被动态地切换和扩展,从而实现系统的灵活性和可扩展性。

使用场景

桥接模式通常适用于以下场景:

  1. 在不同的平台上复用性较好的情况下,取得了比继承更好的优化效果。
  2. 系统实现需要在抽象化角色和具体实现化角色之间增加更多的灵活性和可扩展性。
  3. 一个类存在两个或多个独立变化的维度,且这两个或多个维度都需要进行扩展。

优缺点

优点:

  • 分离抽象部分和具体实现部分,使得设计更加灵活,并且可以在不改变抽象部分的情况下改变具体实现部分。
  • 优秀的扩展能力,可以在两个独立变化的维度上进行扩展。
  • 实现细节对客户端透明,降低了客户端用代码的复杂度。

缺点:

  • 桥接模式的应用需要开发者很好地认识抽象化和实现化两个独立变化的角色,如果设计不够合理,则会造成系统结构混乱。
  • 由于抽象化角色和具体实现化角色之间通过聚合关联,增加了系统的实现复杂度。

实例

下面可以通过一个实例来说明桥接模式的应用。假设我们有一个画图软件,这个画图软件提供了画圆形和矩形这两种图形的功能,而且这些图形可以按照不同的颜色进行填充。因此,我们可以将这个画图软件看成由图形和颜色两个维度组成的一个系统,而由于这两个维度都会发生变化,因此我们就可以使用桥接模式来实现这个系统。

首先,我们需要定义抽象化角色和具体实现化角色,这里我们定义Shape作为抽象化角色,Color作为具体实现化角色。其次,我们需要定义抽象化角色和具体实现化角色之间的桥梁,也就是Color接口。最终,实现具体的图形和颜色类。

下面是这个实例的UML类图:

桥接模式实例UML类图

// Color.java (Implementor)
public abstract class Color {
    public abstract String getColor();
}

// RedColor.java (ConcreteImplementor)
public class RedColor extends Color {
    @Override public String getColor() {
        return "Red";
    }
}

// BlueColor.java (ConcreteImplementor)
public class BlueColor extends Color {
    @Override public String getColor() {
        return "Blue";
    }
}

// Shape.java (Abstraction)
public abstract class Shape {
    protected Color color;

    public Shape(Color color) {
        this.color = color;
    }

    abstract public String draw();
}

// Circle.java (RefinedAbstraction)
public class Circle extends Shape {
    public Circle(Color color) {
        super(color);
    }

    @Override public String draw() {
        return "Circle drawn. " + color.getColor() + " color filled.";
    }
}

// Rectangle.java (RefinedAbstraction)
public class Rectangle extends Shape {
    public Rectangle(Color color) {
        super(color);
    }

    @Override public String draw() {
        return "Rectangle drawn. " + color.getColor() + " color filled.";
    }
}

在上述代码中,我们定义了Color抽象化角色、RedColor和BlueColor两种具体实现化角色。同时,我们还定义了Shape抽象化角色和Circle以及Rectangle两种具体实现化角色。最后,Circle和Rectangle类中的绘图操作draw(),都依赖于一个具体实现化角色Color,而这个具体实现化角色Color类的具体实现可以在运行时动态地指定。这也就是桥接模式的典型应用。

总结

桥接模式的核心在于将抽象化部分和具体实现化部分分离开来,并且通过聚合关联的方式让它们能够在运行时动态地组合在一起,从而达到系统的灵活性和可扩展性的目的。桥接模式通常适用于两个或多个维度上独立变化的系统,可以在两个维度上进行扩展,从而实现功能的增加。

桥接模式的优点在于分离了抽象部分和具体实现部分,使得系统更加灵活,具有较好的扩展性,同时实现细节对客户端透明,减少了代码复杂度。缺点在于如果设计不是很合理,可能会造成系统结构的混乱,因此,在应用桥接模式时一定要根据具体的情况进行谨慎分析和设计。