当前位置: 首页 > news >正文

设计模式:桥接模式(Bridge Pattern)

文章目录

    • 一、桥接模式的定义
    • 二、为什么需要桥接模式?
    • 三、示例代码

一、桥接模式的定义

  桥接模式是一种结构型设计模式,它的主要作用是将抽象部分与实现部分分离,使它们能够独立变化。换句话说,就是把“抽象”和“实现”放到两个独立的类层次中,通过组合而不是继承来连接它们。

桥接模式结构:
在这里插入图片描述

二、为什么需要桥接模式?

问题:
假如有一个几何形状Shape类, 从它能扩展出两个子类: ​ 圆形Circle和 方形Square 。 你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为 红色Red和 蓝色Blue的形状子类。 但是, 由于你已有两个子类, 所以总共需要创建四个类才能覆盖所有组合, 例如蓝色圆形Blue­Circle和红色方形Red­Square 。
在这里插入图片描述

在层次结构中新增形状和颜色将导致代码复杂程度指数增长。 例如添加三角形状, 你需要新增两个子类, 也就是每种颜色一个; 此后新增一种新颜色需要新增三个子类, 即每种形状一个。 如此以往, 情况会越来越糟糕。

解决方案:
问题的根本原因是我们试图在两个独立的维度——形状与颜色——上扩展形状类。 这在处理类继承时是很常见的问题。
桥接模式通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
在这里插入图片描述
根据该方法, 我们可以将颜色相关的代码抽取到拥有红色和蓝色两个子类的颜色类中, 然后在形状类中添加一个指向某一颜色对象的引用成员变量。 现在, 形状类可以将所有与颜色相关的工作委派给连入的颜色对象。 这样的引用就成为了形状和颜色之间的桥梁。 此后, 新增颜色将不再需要修改形状的类层次, 反之亦然。

桥接模式 UML 类图:

        Abstraction(形状)|vRefinedAbstraction(圆形/矩形)|| has-avImplementor(颜色接口)|---------------------|                   |
ConcreteImplementorA   ConcreteImplementorB(红色)                 (蓝色)

桥接模式的角色:

  1. 抽象类(Abstraction):定义抽象接口,包含一个实现类的引用。
  2. 扩展抽象类(RefinedAbstraction):在抽象类的基础上扩展功能。
  3. 实现接口(Implementor):定义实现部分的接口。
  4. 具体实现类(ConcreteImplementor):实现具体的实现逻辑。

示例:形状 + 颜色

#include <iostream>
#include <memory>
using namespace std;// 实现部分(Implementor)
class Color {
public:virtual void applyColor() = 0;virtual ~Color() = default;
};// 具体实现类
class Red : public Color {
public:void applyColor() override {cout << "Red" << endl;}
};class Blue : public Color {
public:void applyColor() override {cout << "Blue" << endl;}
};// 抽象部分(Abstraction)
class Shape {
protected:shared_ptr<Color> color; // 桥接
public:Shape(shared_ptr<Color> c) : color(c) {}virtual void draw() = 0;virtual ~Shape() = default;
};// 扩展抽象类
class Circle : public Shape {
public:Circle(shared_ptr<Color> c) : Shape(c) {}void draw() override {cout << "Drawing Circle in ";color->applyColor();}
};class Rectangle : public Shape {
public:Rectangle(shared_ptr<Color> c) : Shape(c) {}void draw() override {cout << "Drawing Rectangle in ";color->applyColor();}
};// 测试
int main() {shared_ptr<Color> red = make_shared<Red>();shared_ptr<Color> blue = make_shared<Blue>();shared_ptr<Shape> circle = make_shared<Circle>(red);shared_ptr<Shape> rectangle = make_shared<Rectangle>(blue);circle->draw();     // Drawing Circle in Redrectangle->draw();  // Drawing Rectangle in Bluereturn 0;
}

三、示例代码

示例说明:
用图形(圆形、矩形) × 绘制引擎(QPainter 绘制、QSvgGenerator 绘制)

  • 抽象部分(Shape):图形(Circle、Rectangle)
  • 实现部分(DrawAPI):绘制引擎(PainterDraw、SvgDraw)
  • 桥接:Shape 持有 DrawAPI 的指针,可以自由组合。

代码示例:

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QSvgGenerator>
#include <memory>
#include <iostream>// 实现部分接口(DrawAPI)
class DrawAPI {
public:virtual void drawCircle(QWidget *widget, int x, int y, int r) = 0;virtual void drawRect(QWidget *widget, int x, int y, int w, int h) = 0;virtual ~DrawAPI() = default;
};// 具体实现1:用 QPainter 绘制
class PainterDraw : public DrawAPI {
public:void drawCircle(QWidget *widget, int x, int y, int r) override {QPainter p(widget);p.setPen(Qt::red);p.drawEllipse(QPoint(x, y), r, r);}void drawRect(QWidget *widget, int x, int y, int w, int h) override {QPainter p(widget);p.setPen(Qt::blue);p.drawRect(x, y, w, h);}
};// 具体实现2:绘制到 SVG 文件
class SvgDraw : public DrawAPI {
public:void drawCircle(QWidget *widget, int x, int y, int r) override {QSvgGenerator generator;generator.setFileName("circle.svg");generator.setSize(QSize(widget->width(), widget->height()));QPainter p(&generator);p.setPen(Qt::red);p.drawEllipse(QPoint(x, y), r, r);}void drawRect(QWidget *widget, int x, int y, int w, int h) override {QSvgGenerator generator;generator.setFileName("rect.svg");generator.setSize(QSize(widget->width(), widget->height()));QPainter p(&generator);p.setPen(Qt::blue);p.drawRect(x, y, w, h);}
};// 抽象部分(Shape)
class Shape {
protected:std::shared_ptr<DrawAPI> drawApi;
public:Shape(std::shared_ptr<DrawAPI> api) : drawApi(api) {}virtual void draw(QWidget *widget) = 0;virtual ~Shape() = default;
};// 扩展抽象:圆形
class Circle : public Shape {int x, y, r;
public:Circle(int _x, int _y, int _r, std::shared_ptr<DrawAPI> api): Shape(api), x(_x), y(_y), r(_r) {}void draw(QWidget *widget) override {drawApi->drawCircle(widget, x, y, r);}
};// 扩展抽象:矩形
class Rectangle : public Shape {int x, y, w, h;
public:Rectangle(int _x, int _y, int _w, int _h, std::shared_ptr<DrawAPI> api): Shape(api), x(_x), y(_y), w(_w), h(_h) {}void draw(QWidget *widget) override {drawApi->drawRect(widget, x, y, w, h);}
};// 测试窗口
class BridgeWidget : public QWidget {std::shared_ptr<Shape> shape1;std::shared_ptr<Shape> shape2;
public:BridgeWidget(QWidget *parent = nullptr) : QWidget(parent) {auto painter = std::make_shared<PainterDraw>();auto svg = std::make_shared<SvgDraw>();// 圆形用 Painter 画在窗口shape1 = std::make_shared<Circle>(100, 100, 50, painter);// 矩形输出到 rect.svgshape2 = std::make_shared<Rectangle>(50, 150, 120, 80, svg);}protected:void paintEvent(QPaintEvent *event) override {shape1->draw(this);  // 窗口绘制shape2->draw(this);  // 同时生成 rect.svg}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);BridgeWidget w;w.resize(300, 300);w.show();return app.exec();
}

实现效果:

  • 窗口中会显示一个红色的圆形(QPainter 绘制)。
  • 同时会在程序目录下生成 rect.svg 文件,里面保存一个蓝色矩形(SvgDraw 绘制)。
  • Shape(抽象部分) 和 DrawAPI(实现部分) 解耦。
  • 想要支持新的绘制方式(比如 OpenGLDraw),只需要新建一个实现类,不影响 Shape。
http://www.dtcms.com/a/353532.html

相关文章:

  • C# 使用抽象工厂模式实现花园规划系统的设计与实现
  • electron离线开发核心环境变量npm_config_cache
  • python自学笔记14 NumPy 线性代数
  • 嵌入式linux相机(1)
  • Chrome插件开发【storage】
  • 重学JS-005 --- JavaScript算法与数据结构(五)回顾 DOM 操作
  • 实战Kaggle比赛:狗的品种识别(ImageNet Dogs)
  • SpringBoot整合RabbitMQ:从消息队列基础到高可用架构实战指南
  • 视频孪生技术在人工智能领域的应用价值:从虚实融合到智能决策
  • 人工智能在医疗风险预警中的技术应用综述
  • 《零基础入门AI: 目标检测基础知识》
  • Apache Commons Lang 3
  • 设备电机状态监测:通往预测性维护与效能飞升之路
  • AutoMQ 荣获 AWS Differentiated Partner 顶级认证!
  • 基于改进蜂群优化算法的高频金融波动率预测系统 (源码+论文+部署+安装)
  • ES02-常用API
  • qt c++ QTableWidget
  • Gopher URL协议与SSRF二三事
  • 帕累托优化:多目标决策的智慧与艺术
  • “下一代”图像模型——ComfyUI-Flux-Krea本地部署教程,体验划时代的图像质量
  • 计算机视觉(三):opencv环境搭建和图片显示
  • Optional 从 Java 8 到 21 的演进之路
  • 每日算法题【链表】:链表分割、链表的回文结构
  • 关于vscode的右键常用操作以及自定义快捷键
  • 密码管理中注释与重定向密码安全隐患及修复方案
  • 高并发内存池(12)-ThreadCache回收内存
  • Virtual PLCnext Controller 本地网络部署平台
  • Pandas DataFrame 列数操作完全指南
  • 高通平台蓝牙学习-- 基于WCN685x 的蓝牙低功耗(LE)功能
  • 浏览器与计算机网络