设计模式- 桥接模式(Bridge Pattern)结构|原理|优缺点|场景|示例

发布于:2024-04-24 ⋅ 阅读:(17) ⋅ 点赞:(0)

                            ​​​​​​​        设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式        责任链模式        命令模式

                                   备忘录模式          状态模式          访问者模式        中介者模式    


桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与其实现部分分离,使它们可以独立地变化。桥接模式通过引入桥接接口,使得抽象类和实现类可以分别独立扩展,从而解决了多维度变化的问题。这种模式特别适用于那些接口部分和实现部分都需要独立扩展的场景。

模式结构

桥接模式通常包含以下角色:

  1. 抽象类(Abstraction):定义了抽象接口,并维护一个对实现类对象的引用。抽象类不关心具体的实现细节,仅通过接口与实现类交互。

  2. 实现接口(Implementor):定义了实现类需要实现的接口,供抽象类调用。

  3. 具体抽象类(Concrete Abstraction):继承自抽象类,实现了抽象类中与业务相关的操作,并通过构造函数传入实现类对象。具体抽象类可以有多个,每个对应不同的业务场景。

  4. 具体实现类(Concrete Implementor):实现了实现接口,提供了接口的具体实现。具体实现类可以有多个,每个对应不同的实现方式。

工作原理

  • 客户端:通过具体抽象类与系统交互,不需要关心具体的实现细节。
  • 抽象类:定义了抽象接口,并通过持有实现类对象的引用,调用其实现接口的方法。
  • 实现接口:定义了实现类需要实现的通用接口。
  • 具体抽象类:根据具体业务场景,继承抽象类并实现相关业务方法,通过构造函数传入具体的实现类对象。
  • 具体实现类:提供了实现接口的具体实现,供具体抽象类调用。

优缺点

优点
  • 分离抽象与实现:桥接模式将抽象部分与实现部分分离,使得两者可以独立扩展,降低了耦合性。
  • 支持多维度变化:桥接模式可以应对一个类具有两个或多个独立变化维度的情况,每个维度可以通过继承独立扩展。
  • 提高可扩展性:新增抽象类和具体实现类时,不会影响已有的代码,提高了系统的可扩展性。
缺点
  • 增加复杂性:桥接模式引入了额外的抽象层和实现层,增加了系统的复杂性,尤其是对于简单的系统,可能过度设计。
  • 识别抽象和实现的维度困难:识别出系统中独立变化的维度并不总是容易,需要深入理解业务需求和未来可能的变化。

适用场景

  • 系统需要在多个维度上进行变化:当一个系统需要在抽象层次和实现层次上进行独立扩展时,可以使用桥接模式。
  • 接口与实现分离:当接口和实现可以独立扩展,且希望避免多继承带来的问题时,桥接模式是一个很好的选择。
  • 避免类爆炸:当使用继承来处理多维度变化导致类数量急剧增长时,桥接模式可以有效减少类的数量。

代码示例(以Java为例)

// 实现接口
interface DrawingAPI {
    void drawCircle(double x, double y, double radius);
}

// 具体实现类
class DrawingAPI1 implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius) {
        System.out.println("DrawingAPI1 drawing a circle at (" + x + ", " + y + ") radius " + radius);
    }
}

class DrawingAPI2 implements DrawingAPI {
    @Override
    public void drawCircle(double x, double y, double radius) {
        System.out.println("DrawingAPI2 drawing a circle at (" + x + ", " + y + ") radius " + radius);
    }
}

// 抽象类
abstract class Shape {
    protected DrawingAPI drawingAPI;

    protected Shape(DrawingAPI drawingAPI) {
        this.drawingAPI = drawingAPI;
    }

    abstract void draw();
}

// 具体抽象类
class CircleShape extends Shape {
    private double x, y, radius;

    public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
        super(drawingAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    @Override
    void draw() {
        drawingAPI.drawCircle(x, y, radius);
    }
}

// 客户端代码
public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape circle1 = new CircleShape(1, 2, 3, new DrawingAPI1());
        circle1.draw();  // 输出:DrawingAPI1 drawing a circle at (1.0, 2.0) radius 3.0

        Shape circle2 = new CircleShape(4, 5, 6, new DrawingAPI2());
        circle2.draw();  // 输出:DrawingAPI2 drawing a circle at (4.0, 5.0) radius 6.0
    }
}

 在这个Java示例中:

  • DrawingAPI接口定义了绘制圆形的通用接口。
  • DrawingAPI1DrawingAPI2类分别实现了DrawingAPI接口,提供了不同的绘制方式。
  • Shape抽象类定义了抽象接口,并通过构造函数接收一个DrawingAPI对象的引用,实现了与实现类的解耦。
  • CircleShape类继承自Shape,实现了draw()方法,并在构造函数中接收绘制位置和半径参数,以及一个DrawingAPI对象的引用。
  • 客户端代码通过创建CircleShape对象,并传入不同的DrawingAPI实现,实现了基于不同绘制方式绘制圆形,而无需关心具体的绘制细节。

代码示例(以Python为例)

# 实现接口(Implementor)
class RenderingEngine:
    """渲染引擎接口"""

    def render_circle(self, x, y, radius):
        raise NotImplementedError()

    def render_rectangle(self, x, y, width, height):
        raise NotImplementedError()


# 具体实现类(Concrete Implementor)
class SketchRenderingEngine(RenderingEngine):
    """素描风格渲染引擎"""

    def render_circle(self, x, y, radius):
        print(f"Sketch rendering engine is drawing a circle at ({x}, {y}) with radius {radius}.")

    def render_rectangle(self, x, y, width, height):
        print(f"Sketch rendering engine is drawing a rectangle at ({x}, {y}) with dimensions ({width}, {height}).")


class WatercolorRenderingEngine(RenderingEngine):
    """水彩风格渲染引擎"""

    def render_circle(self, x, y, radius):
        print(f"Watercolor rendering engine is painting a circle at ({x}, {y}) with radius {radius}.")

    def render_rectangle(self, x, y, width, height):
        print(f"Watercolor rendering engine is painting a rectangle at ({x}, {y}) with dimensions ({width}, {height}).")


# 抽象类(Abstraction)
class Shape:
    """图形抽象类"""

    def __init__(self, rendering_engine):
        self.rendering_engine = rendering_engine

    def draw(self):
        raise NotImplementedError()


# 具体抽象类(Concrete Abstraction)
class Circle(Shape):
    """圆形"""

    def __init__(self, x, y, radius, rendering_engine):
        super().__init__(rendering_engine)
        self.x = x
        self.y = y
        self.radius = radius

    def draw(self):
        self.rendering_engine.render_circle(self.x, self.y, self.radius)


class Rectangle(Shape):
    """矩形"""

    def __init__(self, x, y, width, height, rendering_engine):
        super().__init__(rendering_engine)
        self.x = x
        self.y = y
        self.width = width
        self.height = height

    def draw(self):
        self.rendering_engine.render_rectangle(self.x, self.y, self.width, self.height)


# 客户端代码
if __name__ == "__main__":
    # 创建图形与渲染引擎
    circle_sketch = Circle(1, 2, 3, SketchRenderingEngine())
    circle_watercolor = Circle(4, 5, 6, WatercolorRenderingEngine())
    rect_sketch = Rectangle(7, 8, 9, 10, SketchRenderingEngine())
    rect_watercolor = Rectangle(11, 12, 13, 14, WatercolorRenderingEngine())

    # 绘制图形
    circle_sketch.draw()
    circle_watercolor.draw()
    rect_sketch.draw()
    rect_watercolor.draw()

在这个例子中,我们将模拟一个图形系统,它允许用户绘制不同形状(如圆形、矩形),同时支持多种渲染引擎(如素描风格、水彩风格)。桥接模式在这里帮助我们将图形的抽象定义(形状)与具体的渲染实现(渲染引擎)分离,使得这两部分可以独立扩展。 

在这个Python示例中:

  • RenderingEngine接口定义了绘制圆形和矩形的通用方法。
  • SketchRenderingEngineWatercolorRenderingEngine类分别实现了RenderingEngine接口,提供了不同的绘制风格。
  • Shape抽象类定义了抽象接口,并通过构造函数接收一个RenderingEngine对象的引用,实现了与实现类的解耦。
  • CircleRectangle类继承自Shape,实现了draw()方法,并在构造函数中接收几何属性参数,以及一个RenderingEngine对象的引用。
  • 客户端代码通过创建不同类型的Shape对象,并传入不同的RenderingEngine实现,实现了基于不同渲染风格绘制图形,而无需关心具体的绘制细节。