C++设计模式外观模式(Facade)

什么是桥接模式?

桥接模式(Bridge Pattern)是一种结构型设计模式,它的核心目的是解耦 抽象部分和实现部分,让它们可以独立变化。在简单的描述中,桥接模式可以让你在不修改原有代码的情况下,分别改变抽象的功能具体的实现

假设你正在开发一个图形绘制程序,它涉及到多个图形(比如圆形、方形)和不同的绘制方式(如屏幕绘制、打印机绘制)。如果将所有图形和绘制方式写在一起,每次新增图形或绘制方式时,都需要修改很多代码,这样不仅增加了复杂性,还不容易维护。

桥接模式的解决思路是:将**图形(抽象)绘制方式(实现)**分开,给每一部分提供独立的变化空间。这样,添加新的图形或新的绘制方式时,只需要扩展新的类即可,而不需要修改现有的代码。

桥接模式的结构

桥接模式的关键在于将抽象层实现层分开,通过"桥"将它们连接起来。它有两个主要组成部分:

  1. 抽象部分:表示具体的功能或对象,比如图形类型(圆形、方形等)。
  2. 实现部分:表示具体的实现方式,比如绘制图形的具体方法(屏幕绘制、打印机绘制等)。

这两个部分是独立的,它们通过桥接连接,从而能够独立发展和变化。

桥接模式的代码示例

为了更好地理解桥接模式,我们来做一个简单的图形绘制程序,支持不同的图形(圆形、方形)和不同的绘制方式(屏幕绘制、打印机绘制)。我们将通过桥接模式来解耦这两个方面。

cpp 复制代码
#include <iostream>
#include <string>

// 绘图接口(实现类接口)
class DrawingAPI {
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() = default;
};

// 具体实现:屏幕绘制
class ScreenDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在屏幕上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

// 具体实现:打印机绘制
class PrinterDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在打印机上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

// 图形类(抽象类)
class Shape {
protected:
    DrawingAPI* drawingAPI;  // 这里持有一个指向绘图实现类的指针

public:
    Shape(DrawingAPI* api) : drawingAPI(api) {}  // 通过构造函数注入具体实现类
    virtual void draw() = 0;  // 绘制图形的接口
    virtual void resize(double factor) = 0;  // 调整图形大小
    virtual ~Shape() = default;
};

// 扩展的具体图形类:圆形
class Circle : public Shape {
private:
    double x, y, radius;  // 圆形的坐标和半径

public:
    Circle(double x, double y, double radius, DrawingAPI* api) 
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() override {
        drawingAPI->drawCircle(x, y, radius);  // 将绘制任务委托给具体实现
    }

    void resize(double factor) override {
        radius *= factor;  // 调整圆形的半径
    }
};

int main() {
    ScreenDrawingAPI screenAPI;  // 创建屏幕绘制实现
    PrinterDrawingAPI printerAPI;  // 创建打印机绘制实现

    // 创建圆形对象,使用不同的绘制方式
    Circle circle1(1, 2, 3, &screenAPI);  // 在屏幕上绘制
    Circle circle2(5, 6, 4, &printerAPI);  // 在打印机上绘制

    circle1.draw();  // 屏幕绘制圆形
    circle2.draw();  // 打印机绘制圆形

    circle1.resize(2.0);  // 改变圆形大小
    circle1.draw();  // 再次绘制,使用屏幕绘制

    return 0;
}

代码讲解

让我们来逐步分析这段代码,理解桥接模式如何起作用。

1. 绘图接口(DrawingAPI
cpp 复制代码
class DrawingAPI {
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() = default;
};

DrawingAPI 是一个抽象接口,它定义了绘制图形的方法 drawCircle。具体的绘制方式(如屏幕绘制或打印机绘制)需要实现这个接口。

2. 具体的绘图实现(ScreenDrawingAPIPrinterDrawingAPI
cpp 复制代码
class ScreenDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在屏幕上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

class PrinterDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在打印机上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

这两个类分别实现了 DrawingAPI 接口,提供了不同的绘制方式:ScreenDrawingAPI 在屏幕上绘制圆形,而 PrinterDrawingAPI 在打印机上绘制圆形。

3. 抽象类(Shape
cpp 复制代码
class Shape {
protected:
    DrawingAPI* drawingAPI;  // 持有一个绘图实现类的指针

public:
    Shape(DrawingAPI* api) : drawingAPI(api) {}  // 通过构造函数注入具体的绘图实现
    virtual void draw() = 0;  // 绘制图形的接口
    virtual void resize(double factor) = 0;  // 调整图形大小
};

Shape 是一个抽象类,定义了所有图形(如圆形、方形)的共同接口:draw()resize()。它通过持有 DrawingAPI 指针将具体的绘制任务委托给实现类,从而将图形抽象部分与绘制实现部分分开。

4. 具体图形类(Circle
cpp 复制代码
class Circle : public Shape {
private:
    double x, y, radius;  // 圆形的坐标和半径

public:
    Circle(double x, double y, double radius, DrawingAPI* api) 
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() override {
        drawingAPI->drawCircle(x, y, radius);  // 调用具体绘图实现的drawCircle方法
    }

    void resize(double factor) override {
        radius *= factor;  // 改变圆形的半径
    }
};

Circle 类继承自 Shape,并实现了 draw()resize() 方法。它将图形绘制的任务委托给 drawingAPI,从而实现了图形的抽象和绘制方式的解耦。

5. 客户端代码

main 函数中,我们创建了两个 Circle 对象,分别使用了 ScreenDrawingAPIPrinterDrawingAPI 作为绘制实现。通过调用 circle1.draw()circle2.draw(),我们看到两种不同的绘制方式。

cpp 复制代码
int main() {
    ScreenDrawingAPI screenAPI;  // 屏幕绘制实现
    PrinterDrawingAPI printerAPI;  // 打印机绘制实现

    // 创建两个圆形对象,分别使用不同的绘制方式
    Circle circle1(1, 2, 3, &screenAPI);
    Circle circle2(5, 6, 4, &printerAPI);

    circle1.draw();  // 屏幕绘制圆形
    circle2.draw();  // 打印机绘制圆形

    circle1.resize(2.0);  // 改变圆形大小
    circle1.draw();  // 再次绘制,使用屏幕绘制

    return 0;
}

总结

桥接模式的核心思想就是解耦抽象和实现部分,它们可以独立变化,而不相互影响。在这个例子中,图形类(

Circle)和绘图方式(如 ScreenDrawingAPIPrinterDrawingAPI)通过桥接模式分离开来,增加新的图形类型或绘制方式时,我们只需要扩展新类,而不需要修改现有代码。这样做让系统更加灵活和可扩展。

完整代码

cpp 复制代码
#include <iostream>
#include <string>

// 绘图接口(实现类接口)
class DrawingAPI {
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() = default;
};

// 具体实现:屏幕绘制
class ScreenDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在屏幕上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

// 具体实现:打印机绘制
class PrinterDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "在打印机上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;
    }
};

// 图形类(抽象类)
class Shape {
protected:
    DrawingAPI* drawingAPI;  // 这里持有一个指向绘图实现类的指针

public:
    Shape(DrawingAPI* api) : drawingAPI(api) {}  // 通过构造函数注入具体实现类
    virtual void draw() = 0;  // 绘制图形的接口
    virtual void resize(double factor) = 0;  // 调整图形大小
    virtual ~Shape() = default;
};

// 扩展的具体图形类:圆形
class Circle : public Shape {
private:
    double x, y, radius;  // 圆形的坐标和半径

public:
    Circle(double x, double y, double radius, DrawingAPI* api) 
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() override {
        drawingAPI->drawCircle(x, y, radius);  // 将绘制任务委托给具体实现
    }

    void resize(double factor) override {
        radius *= factor;  // 调整圆形的半径
    }
};

int main() {
    ScreenDrawingAPI screenAPI;  // 创建屏幕绘制实现
    PrinterDrawingAPI printerAPI;  // 创建打印机绘制实现

    // 创建圆形对象,使用不同的绘制方式
    Circle circle1(1, 2, 3, &screenAPI);  // 在屏幕上绘制
    Circle circle2(5, 6, 4, &printerAPI);  // 在打印机上绘制

    // 绘制圆形
    circle1.draw();  // 屏幕绘制圆形
    circle2.draw();  // 打印机绘制圆形

    // 调整圆形大小
    circle1.resize(2.0);  // 改变圆形大小
    circle1.draw();  // 再次绘制,使用屏幕绘制

    return 0;
}

结果输出:

在屏幕上绘制圆形,位置: (1, 2), 半径: 3
在打印机上绘制圆形,位置: (5, 6), 半径: 4
在屏幕上绘制圆形,位置: (1, 2), 半径: 6

这个实现展示了如何使用桥接模式解耦图形的抽象(Shape)和具体的绘制实现(DrawingAPI),让你可以独立地扩展图形类型和绘制方式,而不影响已有的代码结构。

本文由mdnice多平台发布

相关推荐
雪靡2 小时前
正确获得Windows版本的姿势
c++·windows
可涵不会debug2 小时前
【C++】在线五子棋对战项目网页版
linux·服务器·网络·c++·git
AI+程序员在路上2 小时前
C#调用c++dll的两种方法(静态方法和动态方法)
c++·microsoft·c#
mit6.8243 小时前
What is Json?
c++·学习·json
灶龙3 小时前
浅谈 PID 控制算法
c++·算法
菜还不练就废了3 小时前
蓝桥杯算法日常|c\c++常用竞赛函数总结备用
c++·算法·蓝桥杯
新知图书4 小时前
Linux C\C++编程-文件位置指针与读写文件数据块
linux·c语言·c++
qystca4 小时前
异或和之和
数据结构·c++·算法·蓝桥杯
涛ing5 小时前
19. C语言 共用体(Union)详解
java·linux·c语言·c++·vscode·算法·visual studio
mit6.8245 小时前
[实现Rpc] 项目设计 | 服务端模块划分 | rpc | topic | server
网络·c++·笔记·rpc·架构