设计模式之桥接模式

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。桥接模式通过组合的方式将抽象与实现解耦,从而提高系统的灵活性和可扩展性。

使用场景

  1. 避免类层次结构的爆炸
    当一个系统需要在多个维度上扩展时,使用继承会导致类的数量急剧增加。桥接模式通过分离抽象和实现,避免类层次结构的爆炸。

    示例:在图形绘制系统中,不同形状(如圆形、矩形)可以用不同颜色(如红色、蓝色)绘制。使用继承会导致大量的子类,而桥接模式可以有效地解决这个问题。

  2. 独立地变化抽象和实现
    当一个系统的抽象部分和实现部分需要独立变化时,可以使用桥接模式。抽象部分和实现部分可以分别独立扩展,而不会相互影响。

    示例:在操作系统的文件系统中,文件抽象可以有不同的存储方式(如本地存储、云存储),使用桥接模式可以让文件抽象和存储实现独立变化。

  3. 跨平台开发
    当一个系统需要跨平台开发时,可以使用桥接模式将抽象部分和平台相关的实现部分分离,从而实现跨平台的灵活性。

    示例:在跨平台图形库中,抽象部分定义了绘制接口,不同平台(如Windows、Linux)有不同的实现。

UML类图

+-------------------+       +-------------------+
|     Abstraction   |<>---->|   Implementor     |
+-------------------+       +-------------------+
| -impl: Implementor|       | +operationImpl()  |
| +operation()      |       +-------------------+
+-------------------+               /|\
                                      |
                                      |
                      +----------------------------+
                      |                            |
          +-------------------+        +-------------------+
          | RefinedAbstraction|        | ConcreteImplementor|
          +-------------------+        +-------------------+
          | +operation()      |        | +operationImpl()  |
          +-------------------+        +-------------------+

类图解释

  1. Abstraction(抽象类)

    • 职责:定义抽象部分的接口,持有一个 Implementor 对象的引用。可以包含一些通用的行为或方法。
    • 属性:持有一个 Implementor 类型的成员变量 impl
    • 方法
      • operation():定义一个操作接口,具体的行为由实现部分的 operationImpl 方法完成。
  2. RefinedAbstraction(扩展抽象类)

    • 职责:扩展 Abstraction 类,提供更具体的实现,通常会调用 Implementor 的方法来实现操作。
    • 方法
      • operation():可以在这里调用 imploperationImpl 方法来实现具体的操作。
  3. Implementor(实现类接口)

    • 职责:定义实现部分的接口,不同的实现类需要实现这个接口。
    • 方法
      • operationImpl():实现具体操作的方法,抽象部分通过这个接口与具体实现部分交互。
  4. ConcreteImplementor(具体实现类)

    • 职责:实现 Implementor 接口,提供具体的实现方法。
    • 方法
      • operationImpl():具体的实现方法,完成实际的操作。

工作流程

  1. Abstraction 持有 Implementor 的引用

    • Abstraction 类中有一个 Implementor 类型的成员变量,这个变量指向具体的实现对象。
  2. RefinedAbstraction 扩展 Abstraction

    • RefinedAbstraction 类扩展了 Abstraction 类,并实现了具体的操作方法。
  3. Implementor 定义实现接口

    • Implementor 是一个接口或抽象类,定义了实现部分的操作接口。
  4. ConcreteImplementor 实现 Implementor 接口

    • ConcreteImplementor 类实现了 Implementor 接口,提供了具体的实现方法。
  5. 通过组合实现解耦

    • Abstraction 类通过组合的方式持有 Implementor 对象的引用,而不是继承,实现在多个维度上的独立变化。

示例代码

假设我们有一个图形绘制系统,不同形状(如圆形、矩形)可以用不同颜色(如红色、蓝色)绘制。我们用桥接模式来实现这个场景。

#include <iostream>
#include <memory>

// 实现接口
class Color {
public:
    virtual void applyColor() = 0;
    virtual ~Color() = default;
};

// 具体实现类:红色
class RedColor : public Color {
public:
    void applyColor() override {
        std::cout << "Applying red color." << std::endl;
    }
};

// 具体实现类:蓝色
class BlueColor : public Color {
public:
    void applyColor() override {
        std::cout << "Applying blue color." << std::endl;
    }
};

// 抽象类
class Shape {
public:
    Shape(std::unique_ptr<Color> color) : color_(std::move(color)) {}
    virtual void draw() = 0;
    virtual ~Shape() = default;

protected:
    std::unique_ptr<Color> color_;
};

// 扩充抽象类:圆形
class Circle : public Shape {
public:
    Circle(std::unique_ptr<Color> color) : Shape(std::move(color)) {}
    void draw() override {
        std::cout << "Drawing Circle. ";
        color_->applyColor();
    }
};

// 扩充抽象类:矩形
class Rectangle : public Shape {
public:
    Rectangle(std::unique_ptr<Color> color) : Shape(std::move(color)) {}
    void draw() override {
        std::cout << "Drawing Rectangle. ";
        color_->applyColor();
    }
};

// 客户端代码
int main() {
    std::unique_ptr<Shape> redCircle = std::make_unique<Circle>(std::make_unique<RedColor>());
    redCircle->draw();

    std::unique_ptr<Shape> blueRectangle = std::make_unique<Rectangle>(std::make_unique<BlueColor>());
    blueRectangle->draw();

    return 0;
}
代码工作流程
  1. 创建颜色对象

    • 客户端代码创建具体的颜色对象,如 RedColorBlueColor,它们实现了 Color 接口。
  2. 创建形状对象并组合颜色对象

    • 客户端代码创建具体的形状对象,如 CircleRectangle,并将颜色对象传递给它们。这些形状对象通过组合方式持有颜色对象的引用。
  3. 调用 draw 方法

    • 客户端代码调用具体形状对象的 draw 方法。
    • draw 方法内部,形状对象调用 color_ 对象的 applyColor 方法来应用颜色。
  4. 实现形状绘制和颜色应用

    • CircleRectangle 类分别实现了形状的绘制逻辑,并在绘制形状时调用颜色对象的 applyColor 方法,实现形状和颜色的组合绘制。
代码示例结果

通过这种方式,我们实现了形状和颜色的独立变化:

  • 可以轻松添加新的形状类(如三角形),只需要实现 Shape 类的 draw 方法。
  • 可以轻松添加新的颜色类(如绿色),只需要实现 Color 接口的 applyColor 方法。
  • 不同的形状和颜色可以自由组合,如红色的圆形、蓝色的矩形等。

优点

  1. 分离抽象和实现
    可以独立地扩展抽象部分和实现部分,而不会相互影响。

  2. 提高系统的扩展性
    通过组合的方式,可以灵活地扩展系统的功能,增加新的抽象和实现。

  3. 符合开闭原则
    可以在不修改现有代码的情况下,扩展系统的功能,增加新的抽象和实现。

  4. 降低耦合度
    抽象部分和实现部分可以独立变化,降低了系统的耦合度。

缺点

  1. 增加系统的复杂性
    使用桥接模式会增加系统的复杂性,需要定义更多的类和接口。

  2. 需要正确地设计抽象层和实现层
    桥接模式要求有一个较好的设计基础,需要在系统设计初期仔细规划抽象层和实现层的分离。

使用场景总结

  1. 避免类层次结构的爆炸:如图形绘制系统中不同形状和颜色的组合。
  2. 独立地变化抽象和实现:如文件系统中不同存储方式的独立变化。
  3. 跨平台开发:如跨平台图形库中抽象部分和平台相关实现部分的分离。

通过这个例子和解释,可以看到桥接模式在分离抽象和实现、提高系统扩展性和灵活性方面的强大功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值