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

Golang 设计模式系列5: 桥接模式(Bridge Pattern) 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。 在桥接模式结构图中包含如下几个角色: Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个 Implementor(实现类接口)类型的对象并可以维... 阅读详情

一、桥接模式的定义

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

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

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

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

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

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

桥接模式 UML 类图:

        Abstraction(形状)
            |
            v
   RefinedAbstraction(圆形/矩形)
            |
            | has-a
            v
     Implementor(颜色接口)
            |
   ---------------------
   |                   |
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 Red
    rectangle->draw();  // Drawing Rectangle in Blue
    return 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.svg
        shape2 = 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。
探索 .NET 多版本兼容的精美 WinForms UI 控件库:ReaLTaiizor 你可以根据需要修改主题的颜色方案。// 示例:修改主题颜色设置主色和次色。应用到中。通过继承和重写控件的方法,可以实现自定义样式。// 示例:自定义 MetroButton 样式// 自定义绘制逻辑创建类继承自。重写OnPaint方法,添加自定义绘制逻辑。 阅读详情

相关推荐

WhatsApp网页版扫码分析

扫码登录本质上是WhatsApp的多设备登录,设备之间可以独立运行,那么当我们首次通过WhatsApp扫码登录二维码时,到底发生了那些事情?交换了那些数据?

SocialMarketing的博客 5229

设计模式第12讲——桥接模式(Bridge)

桥接模式是一种结构型设计模式。一、什么是桥接模式 二、角色组成 三、优缺点 四、应用场景 4.1 生活场景 4.2 java场景 五、代码实现 5.0 UML类图 5.1实现部分——Bluetooth5.2 具体实现——BluetoothImpl5.3 抽象部分——Phone5.4 具体抽象六、总结

让~学习~成为一种习惯(橡 皮 人の技术博客) 2791

保姆级教程:在RK3576上配置USB网卡从零到外网访问(附udev规则详解)

本文提供了在RK3576开发板上配置USB网卡的完整教程,涵盖从内核驱动、udev规则到网络路由的全流程。重点讲解了如何利用USB Gadget功能实现高速网络连接,并构建稳定的算力集群,确保多设备间通信及外网访问。

grass的博客 454

设计模式之桥接模式

在开始学java的时候老师讲到继承的时候,总是喜欢用一个例子来讲解,那就是画图,这里有一个画笔,可以画正方形、长方形、圆形(这个大家都知道怎么做吧,我就不解释了)。但是现在我们需要给这些形状进行上色,这里有三种颜色:白色、灰色、黑色。这里我们可以画出3*3=9中图形:白色正方形、白色长方形、白色圆形。。。。。。到这里了我们几乎到知道了这里存在两种解决方案: 我们我们采用方案一来实现的话,我们是不是也可以这样来理解呢?为每种颜色都提供各种形状的版本呢?这个是完全的可以的。如下: 对于中两个图形,我们都会很清楚

不吃_花椒的博客 412

Keil5安装包别乱下!手把手教你从官网精准下载C51/V960和MDK5,并完成2032年有效注册(避坑网络资源失效)

本文详细介绍了如何从Keil官网安全下载C51 V9.60和MDK5开发环境,并提供2032年有效注册的完整指南。通过验证安装包完整性、自定义安装路径和长期激活方案,帮助开发者避开网络资源陷阱,搭建稳定的STM32开发环境。

weixin_26886855的博客 528

k8s配置habor作为镜像地址之后,如果harbor中没有镜像,如何设置自动从阿里云官方镜像仓库下载

通过 Harbor 的远端仓库可以集中管理。如果你在上游设置了 image prefix 为 library,那么对外访问 harbor.your-domain.com/library/nginx:latest 就会被 Harbor 去上游拉取 registry.cn-hangzhou.aliyuncs.com/library/nginx:latest 并缓存。- 将集群中的镜像地址改为 Harbor 的域名,比如 harbor.your-domain.com/library/nginx:latest。

极客栈 421

桥接模式(Bridge模式)详解

在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。 当然,这样的例子还有很多,如不同颜色和字体的文字、不同品牌和功率的汽车、不同性别和职业的男女、支持不同平台和不同文件格式的媒体播放器等。如果...

weixin_43893935的博客 2300

实战篇| app爬虫不用真机

之前写过一篇基于真机app爬虫《App爬虫实战篇-以华为真机手机爬取集换社的app为例》,如果大家有用真机爬虫的经历,会深刻认识到真的不方便,一是自己的手机,经常会被电话、微信等打断,二是闲置手机,面对小批量数据还能勉强,大批量爬虫,会导致成本指数级上升,并且控制起来相对麻烦。以下就是常见的模拟器。emulator -avd my_avd -no-snapshot-save # 启动时不保存 snapshot。emulator -avd my_avd -wipe-data # 清除数据(恢复到出厂)

youbingchen的博客 596

第一篇 桥接模式(Bridge Pattern)

第一篇 桥接模式(Bridge Pattern) 文章目录第一篇 桥接模式(Bridge Pattern)一、概述二、原理类图三、实际应用1.手机操作问题 一、概述 桥接模式指的是将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。 桥接模式是一种结构型设计模式 桥接模式基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(Implementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展 二

chen13333336677的博客 386

AI 实战篇 |基于 AI开放平台实现 人脸识别对比 功能,超详细教程【附带源码】

本篇文章来学习一下怎样使用 Unity实现简单地人脸识别 功能。 关于人脸识别,我们可以选择很多平台的SDK接入Unity来实现人脸识别的功能。

努力前行,总会成为自己心中的那道光 5万+

论文阅读:arixv 2025 Poisoning Attacks on LLMs Require a Near-constant Number of Poison Samples

研究者做了目前最大规模的“投毒实验”,训练了从6亿参数到130亿参数的模型(覆盖了中小到大型LLM),用的训练数据量也是“最适合模型大小”的(按行业里的“Chinchilla法则”,模型越大,训练数据量也按比例增加)。总结下来就是:这篇论文告诉我们,给大语言模型投毒,比之前想的容易得多——不需要海量毒数据,只要几百条藏好后门的文档,就能让大模型“带毒工作”,而且平时还看不出来。——这比之前大家担心的“需要投毒数据占训练集一定比例”要可怕得多,因为对大模型来说,“固定数量”的毒数据更容易偷偷塞进去。

CSPhD-winston的博客 1080

设计模式之桥接模式详解(附应用举例实现)

设计模式之桥接模式详解(附应用举例实现)

pursuit的博客 5704

第14.5章 高翔博士最新开源框架Lightning-LM源码解读(五):揭秘位姿图优化核心模块,从数学原理到代码实现

本文介绍了Lightning-LM框架中的位姿图优化(PGO)模块实现。该模块通过融合多源定位信息(激光定位、激光里程计、DR等),构建并优化位姿图来获得更精确的位姿估计。 主要内容包括: 模块概况与数据流程:初始化配置→添加PGO帧→分配位姿→优化求解→更新位姿→滑动窗口 16个核心函数详解:从构造函数到边缘化处理,涵盖完整的PGO工作流程 关键技术点:噪声参数设置、优化问题构建、约束添加、异常值处理等 关键数据结构:帧队列管理、顶点和边构建、优化统计信息收集 该PGO模块采用增量式优化方式,支持多种约束

行知SLAM 1215

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

将抽象与实现分离,使得它们可以独立变化。常用于避免多重继承。

遇见伯灵说的博客 1051

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

桥接模式是一种结构型设计模式,用于将抽象与实现分离,使它们可以独立地变化。桥接模式的核心思想是将一个大类或多个紧密相关的类分为两个独立的层次结构,从而实现解耦。在桥接模式中,存在:抽象部分和实现部分。抽象部分定义了高层逻辑,而实现部分则提供了底层的具体实现。通过将这两个部分分离,并使用桥接模式连接它们,可以在不修改现有代码的情况下方便地扩展和修改系统。

qq_40537587的博客 1039

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

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

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

冀晓武的博客 678

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

设计模式精讲 Day 7:桥接模式(Bridge Pattern)

桥接模式(Bridge Pattern)是一种结构型设计模式,它将一个抽象部分(Abstraction)与它的实现部分(Implementation)分离,使它们可以独立变化。通过组合而非继承的方式,避免类层次结构的膨胀。核心思想抽象部分定义高层操作接口。实现部分提供具体的实现逻辑。两者通过组合建立联系,而不是通过继承。// 实现接口:图形渲染方式// 图形抽象类// 圆形类@Override// 方形类@Override本篇文章详细介绍了桥接模式。

在未来等你的专栏 1129

【图解设计模式系列】The Bridge Pattern: 桥接模式

桥接模式是用于把抽象化与实现化解耦,使得二者可以独立变化。这种模式涉及一个接口,作为一个桥梁,使得具体类的功能独立于接口实现类。两种类型的类可以在结构上改变而不彼此影响。 桥接模式包含如下几个角色: Abstraction:抽象类角色。定义抽象类的接口并维护指向Implementor类的对象指针。 RefinedAbstraction:扩充抽象类。扩充Abstraction定义的接口。 Implementor:定义实现类的接口,该接口不一定要与Abstraction的接口完全一致。事实上这两个接口可以完全

Tech in Pieces 545

【c++设计模式10】结构型2:桥接模式(Bridge Pattern)

定义桥接模式(Bridge Pattern)定义了两个独立变化的维度,即抽象和实现,通过组合的方式将抽象部分和实现部分连接在一起,从而使得它们可以独立地进行扩展和变化。桥接模式通过将抽象部分的方法委派给实现部分,可以使得抽象部分和实现部分可以独立地进行演化。桥接模式通过组合而不是继承的方式实现了两个独立变化维度之间的解耦,提高了系统的灵活性。

junxuezheng的博客 1175

【设计模式自习室】桥接模式 Bridge Pattern:处理多维度变化

前言 《设计模式自习室》系列,顾名思义,本系列文章带你温习常见的设计模式。主要内容有: 该模式的介绍,包括: 引子、意图(大白话解释) 类图、时序图(理论规范) 该模式的代码示例:熟悉该模式的代码长什么样子 该模式的优缺点:模式不是万金油,不可以滥用模式 该模式的应用案例:了解它在哪些重要的源码中被使用 该系列会逐步更新于我的博客和公众号(博客见文章底部),也希望各位观众老爷能够关注我...

蛮三刀酱 1081

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

一,桥接模式,直接上代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _7.桥接模式 { //桥梁模式的用意是"将抽象化与实现化脱耦,使得二者存...

dcujcivw769565的博客 200

设计模式-桥接模式Bridge Pattern:爱虽放手,牵挂不减

概念桥接模式(Bridge Pattern)是设计模式中最复杂的模式之一,它把事物对象和该对象的具体行为、具体特征分离开来,使它们可以独自进行变化和更改。这样的解释可能比较抽象和令人费解,读者可以通过下面的应用场景进一步来理解。应用场景我们还以绘制图形为例,比如我们要绘制矩形Rectangle、Circle、Triangle,我们需要至少需要定义3个形状类来表示,如果我们要绘制的图形还有不同的颜色,如Red、Yello、Green等,此时我们可能有一下两种设计方案:1. 为每个形状类都提供颜色的实现,比如通

fuhua_chou的博客 209

设计模式学习笔记十二:桥接模式(Bridge Pattern)

设计模式学习笔记十二:桥接模式(Bridge Pattern)     1.概述     桥接模式(Bridge),将抽象部分与它的实现部分分离,是他们都可以独立的变化。什么叫抽象与它的实现分离,这并不是说,让抽象类与其他派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。     下面我们看桥接模式的结构图:     (1).Abs

AlbenXie的博客 610

【设计模式】结构型:桥接模式(Bridge Pattern)

桥接模式,有的地方也叫桥梁模式,其定义是:将抽象和实现解耦,使得两者可以独立的变化。定义本身就比较抽象,不好理解,也不太好解释,但请记住,它的重点是解耦二字。不要纠结如何解释它,直接用具体案例来理解桥接模式是如何解耦代码的。

不忘初心 方得始终 483

Python 设计模式: 桥接模式(bridge pattern)

开发十年,就只剩下这套Java开发体系了 &gt;&gt;&gt;    ...

weixin_36646275的博客 246

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

设计模式应用场景 双维度扩展,一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。 实现方式 抽象类聚合接口,分离抽象和实现,使它们都可以独立的变化。 代码实现: 1.定义桥接接口 interface Calculation{ void method(int x,int y); } 2.接口实现 class A implements Calculation{ @Override public void method(int x, int y) { Syst

WindNolose的博客 159
上一篇: 设计模式:适配器模式(Adapter Pattern)
下一篇: 设计模式:组合模式(Composite Pattern)
TechNomad
博客等级 码龄2年 787粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值