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

什么是桥接模式?

桥接模式(Bridge Pattern)是一个用来解耦的设计模式,它将抽象层实现层分离开,让它们可以独立变化。用最简单的话来说,就是让你能够改变抽象的功能具体的实现,而不需要修改对方的代码。

举个例子,想象你在做一个图形绘制的程序,你有很多图形(比如圆形、方形),而且每种图形可能有不同的绘制方式(比如屏幕绘制、打印机绘制)。如果你把所有的图形和绘制方式都写在一起,每次你增加一种新的绘制方式或新图形时,你都要修改大量的代码,这样就会让系统变得很复杂。

桥接模式的思路是:把**图形(抽象)绘制方式(实现)**分开,每一部分都可以独立变化,互不干扰。这样一来,增加新的图形或者新的绘制方式时,就不需要修改现有的代码,只需要扩展新的类即可。

桥接模式的结构

桥接模式有两个重要部分:

  1. 抽象部分(比如图形的类型,如圆形、方形等)
  2. 实现部分(比如具体的绘制方式,如屏幕绘制、打印绘制等)

这两个部分通过“桥”连接起来,形成了一个灵活可扩展的结构。下面的代码结构就能帮助你理解这一点。

桥接模式的代码示例

假设我们要实现一个图形绘制的程序,支持不同的图形(圆形、方形)和不同的绘制方式(屏幕绘制、打印机绘制)。我们来看看怎么用桥接模式来实现。

#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
class DrawingAPI {
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() = default;
};

这个类定义了一个绘制圆形的方法 drawCircle,它只是一个接口,并不做具体的绘制工作。任何具体的绘制方式(比如屏幕绘制、打印机绘制)都需要实现这个接口。

2. 具体的绘图实现(ScreenDrawingAPIPrinterDrawingAPI
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
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
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(),我们可以看到两个不同的绘制方式。

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;
}

总结

桥接模式的主要优点就是解耦

。我们把抽象部分(如图形类型)和实现部分(如绘制方式)分开,避免了两者之间的紧耦合。这样我们可以很方便地扩展新的图形类型或新的绘制方式,而不需要修改现有的代码。

比如,如果你以后需要支持新的绘制方式(比如在Web上绘制),你只需要实现一个新的 DrawingAPI 类,不用改动任何图形类;同样,如果你需要增加新的图形类型(比如矩形),只需要扩展 Shape 类,不需要改动任何绘制实现。

桥接模式适用于需要将抽象和实现分离,并且它们可能会独立变化的场景。

本文由mdnice多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/925529.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【目标跟踪】Anti-UAV数据集详细介绍

Anti-UAV数据集是在2021年公开的专用于无人机跟踪的数据集&#xff0c;该数据集采用RGB-T图像对的形式来克服单个类型视频的缺点&#xff0c;包含了318个视频对&#xff0c;并提出了相应的评估标准&#xff08;the state accurancy, SA)。 文章链接&#xff1a;https://arxiv.…

PyG教程:MessagePassing基类

PyG教程&#xff1a;MessagePassing基类 一、引言二、如何自定义消息传递网络1.构造函数2.propagate函数3.message函数4.aggregate函数5.update函数 三、代码实战1.图数据定义2.实现GNN的消息传递过程3.完整代码4.完整代码的精简版本 四、总结1.MessagePassing各个函数的执行顺…

Win10 系统下使用研华XNavi安装板卡驱动失败

配置&#xff1a;主板 AIMB-705G2&#xff0c;CPU i5-6500&#xff0c;系统 Windows10_64bit_Pro_22H2&#xff0c; 测试&#xff1a; 1、多次安装驱动。FAIL 2、尝试在其他电脑上移植板卡驱动并且使用数字签名安装。FAIL 3、系统更新到WIN10最新版本。FAIL 4、杀毒软件卸…

用三维模型的顶点法向量计算法线贴图

法线贴图的核心概念是在不增加额外多边形数目的情况下&#xff0c;通过模拟细节来改善光照效果。具体流程包括&#xff1a; 法线的计算与存储&#xff1a;通过法线映射将三维法线向量转化为法线贴图的 RGB 值。渲染中的使用&#xff1a;在片段着色器中使用法线贴图来替代原有的…

idea编译与maven编译的问题

先说下idea编译按钮的位置 编译运行时&#xff0c;会在idea底部出现Build面板 比较&#xff1a; idea编译器编译整个项目 maven编译器根据pom.xml的配置&#xff0c;可实现灵活编译 两套编译会遇到的问题&#xff1a; maven 编译成功 &#xff0c;但idea编译失败&#xff…

deepin 安装 chrome 浏览器

deepin 安装 chrome 浏览器 最近好多小伙伴儿和我说 deepin 无法安装最新的谷歌浏览器 其实是因为最新的 谷歌浏览器 其中的一个依赖需要提前安装 提前安装依赖然后再安装谷歌浏览器就可以了 安装 fonts-liberationsudo apt -y install fonts-liberation安装 chrome 浏览器sudo…

《String类》

目录 一、定义与概述 二、创建字符串对象 2.1 直接赋值 2.2 使用构造函数 三、字符串的不可变性 四、常用方法 4.1 String对象的比较 4.1.1 比较是否引用同一个对象 4.1.2 boolean equals(Object anObject)方法&#xff1a;按照字典序比较 4.1.3 int compareTo(Strin…

OpenSSH-9.9p1 OpenSSL-3.4.0 升级步骤详细

前言 收到漏洞扫描通知 OpenSSH 安全漏洞(CVE-2023-38408) OpenSSH 安全漏洞(CVE-2023-51385) OpenSSH 安全漏洞(CVE-2023-51384) OpenSSH 安全漏洞(CVE-2023-51767) OpenSSH 安全漏洞(CVE-2023-48795) OpenSSH&#xff08;OpenBSD SecureShell&#xff09;是加拿大OpenBSD计划…

【Stable Diffusion】安装教程

目录 一、python 安装教程 二、windows cuda安装教程 三、Stable Diffusion下载 四、Stable Diffusion部署&#xff08;重点&#xff09; 一、python 安装教程 &#xff08;1&#xff09;第一步下载 打开python下载页面&#xff0c;找到python3.10.9&#xff0c;点击右边…

Scala身份证上的秘密以及Map的遍历

object test {def main(args: Array[String]): Unit {val id "42032220080903332x"//1.生日是&#xff1f;//字符串截取val birthday id.substring(10,14) //不包括终点下标println(birthday)val year id.substring(6,10) //println(year)//性别&#xff1a;倒数第…

springboot 异步 @Async 的日常使用及失效场景

文章目录 springboot 异步 Async 的日常使用引言一、Async 使用位置二、Async 使用三、注解 Async 失效的情况&#xff08;1&#xff09;调用同一个类中的异步方法&#xff08;内部调用&#xff09;&#xff08;2&#xff09;未使用 EnableAsync 注解&#xff08;3&#xff09;…

Laravel8.5+微信小程序实现京东商城秒杀方案

一、商品秒杀涉及的知识点 鉴权策略封装掊口访问频次限制小程序设计页面防抖接口调用订单创建事务使用超卖防御 二、订单库存系统方案&#xff08;3种&#xff09; 下单减库存 优点是库存和订单的强一致性&#xff0c;商品不会卖超&#xff0c;但是可能导致恶意下单&#xff…

三角网格体的光滑性问题

三角网格体的光滑性问题 在计算机图形学和计算机辅助设计中&#xff0c;C0连续性&#xff08;也称为位置连续性&#xff09;是指两个曲线或曲面在它们的公共边界上具有相同的位置。这意味着它们在边界处没有缝隙或重叠&#xff0c;但它们的切线方向可以不同。C0连续性是最低级…

独家|京东调整职级序列体系

原有的M、P、T、S主序列将正式合并为新的专业主序列P。 作者|文昌龙 编辑|杨舟 据「市象」独家获悉&#xff0c;京东已在近日在内部宣布对职级序列体系进行调整&#xff0c;将原有的M、P、T、S主序列正式合并为新的专业主序列P&#xff0c;合并后的职级体系将沿用原有专业序…

Echarts 绘制地图

一、Apache Echarts 官网地址&#xff1a;https://echarts.apache.org/ npm install echarts --save 二、获取地图的GeoJSON 地址&#xff1a;DataV.GeoAtlas地理小工具系列 左侧是地图&#xff0c;右侧是JSON数据路径&#xff0c;点击你想要生成的地图省市、地级&#xff0…

想入手养宠宠物空气净化器,养宠宠物空气净化器哪个好?

家里有了宠物后&#xff0c;确实多了很多欢乐&#xff0c;但掉落的毛发也多了不少&#xff0c;特别是换毛期&#xff0c;掉毛问题真的很让人头疼&#xff01;作为养了多年宠物的铲屎官&#xff0c;我真心推荐大家买一台宠物空气净化器&#xff0c;它能大大提升家里的空气质量&a…

ASUS/华硕ROG掌机 2023款 RC71 NR2301原厂win11系统 工厂文件 带ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;一键恢复&#xff0c;以及机器所有驱动软件。 系统版本&#xff1a;windows11 原厂系统下载网址&#xff1a;http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意&#xff1a;仅支持以上型号专用…

nginx 升级http 到 http2

同步发布于我的网站 &#x1f680; 背景介绍准备工作配置过程遇到的问题及解决方法验证升级总结参考资料 背景介绍 HTTP/2 是 HTTP 协议的最新版本&#xff0c;相比 HTTP/1.1&#xff0c;它带来了多项重要的改进&#xff0c;包括多路复用、头部压缩和服务端推送。这些特性可…

Spark 内存管理机制

Spark 内存管理 堆内内存和堆外内存 作为一个 JVM 进程&#xff0c;Executor 的内存管理建立在 JVM(最小为六十四分之一&#xff0c;最大为四分之一)的内存管理之上&#xff0c;此外spark还引入了堆外内存&#xff08;不在JVM中的内存&#xff09;&#xff0c;在spark中是指不…

透视投影(Perspective projection)与等距圆柱投影(Equirectangular projection)

一、透视投影 1.方法概述 Perspective projection&#xff08;透视投影&#xff09;是一种模拟人眼观察三维空间物体时的视觉效果的投影方法。它通过模拟观察者从一个特定视点观察三维场景的方式来创建二维图像。在透视投影中&#xff0c;远处的物体看起来比近处的物体小&…