C++设计模式之——桥接模式详解和代码实例

news2024/11/23 20:17:03

文章目录

    • 桥接模式详解:
    • C++代码实例
    • 进一步阐述桥接模式的优点和适用场景
    • 桥接模式的实际应用场景还包括但不限于以下几种情况:

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与其实现部分分离,使它们都可以独立变化。这种模式有时也被称作柄体(Handle and Body)模式或接口隔离模式。它的主要目的是将抽象层与实现层解耦,使得两者可以独立扩展而互不影响。

桥接模式详解:

  1. 角色定义

    • Abstraction(抽象化角色):定义抽象接口,维护一个对Implementor对象的引用。
    • RefinedAbstraction(具体抽象化角色):是Abstraction的一个子类,对Abstraction接口进行一些补充。
    • Implementor(实现化角色):定义实现化角色的接口,任何Abstraction角色可以调用。
    • ConcreteImplementor(具体实现化角色):Implementor接口的具体实现。
  2. 工作原理

    • 抽象化角色持有实现化角色的引用,它只需要定义与客户端的接口并委托给实现化角色来执行。
    • 具体化角色继承抽象化角色并实现自己的业务逻辑,同时构造时关联相应的实现化角色。

C++代码实例

#include <iostream>

// 实现化角色接口
class Implementor {
public:
    virtual ~Implementor() {}
    virtual void operationImpl() = 0; // 定义操作接口
};

// 具体实现化角色A
class ConcreteImplementorA : public Implementor {
public:
    void operationImpl() override {
        std::cout << "ConcreteImplementorA 的 operationImpl()" << std::endl;
    }
};

// 具体实现化角色B
class ConcreteImplementorB : public Implementor {
public:
    void operationImpl() override {
        std::cout << "ConcreteImplementorB 的 operationImpl()" << std::endl;
    }
};

// 抽象化角色
class Abstraction {
protected:
    Implementor* _implementor;

public:
    Abstraction(Implementor* impl) : _implementor(impl) {}
    virtual ~Abstraction() { delete _implementor; }
    virtual void operation() = 0; // 定义抽象操作
};

// 具体抽象化角色
class RefinedAbstraction : public Abstraction {
public:
    RefinedAbstraction(Implementor* impl) : Abstraction(impl) {}

    void operation() override {
        std::cout << "RefinedAbstraction 调用 operation..." << std::endl;
        _implementor->operationImpl(); // 委托实现化角色执行操作
    }
};

int main() {
    Abstraction* absA = new RefinedAbstraction(new ConcreteImplementorA());
    absA->operation();

    Abstraction* absB = new RefinedAbstraction(new ConcreteImplementorB());
    absB->operation();

    delete absA;
    delete absB;

    return 0;
}

在这个例子中,Abstraction是抽象化角色,RefinedAbstraction是具体抽象化角色,Implementor是实现化角色接口,ConcreteImplementorAConcreteImplementorB是具体实现化角色。通过改变构造Abstraction时传入的Implementor的不同实现,我们可以轻松切换不同的行为方式。

桥接模式的核心价值在于它能分离抽象和实现,让两者可以独立演化。下面是对上述代码实例的进一步解释:

  1. 抽象化角色(Abstraction):定义了抽象的操作operation(),但不提供具体实现。它通过维持一个指向Implementor的指针来间接使用其实现。
class Abstraction {
protected:
    Implementor* _implementor;

public:
    // 构造函数接收一个Implementor对象的指针
    Abstraction(Implementor* impl) : _implementor(impl) {}
    virtual ~Abstraction() { delete _implementor; }

    // 定义抽象操作
    virtual void operation() = 0;
};
  1. 具体抽象化角色(RefinedAbstraction):继承自Abstraction,在operation()中调用了_implementoroperationImpl()方法,这样就把具体实现细节交给了实现化角色。
class RefinedAbstraction : public Abstraction {
public:
    RefinedAbstraction(Implementor* impl) : Abstraction(impl) {}

    // 实现抽象操作,调用Implementor的实现
    void operation() override {
        std::cout << "RefinedAbstraction 调用 operation..." << std::endl;
        _implementor->operationImpl();
    }
};
  1. 实现化角色(Implementor):定义了所有实现类共有的接口operationImpl(),它是抽象化角色依赖的具体操作。
class Implementor {
public:
    virtual ~Implementor() {}
    // 实现化角色的接口
    virtual void operationImpl() = 0;
};
  1. 具体实现化角色(ConcreteImplementorA/B):分别提供了operationImpl()的不同实现。
class ConcreteImplementorA : public Implementor {
public:
    void operationImpl() override {
        std::cout << "ConcreteImplementorA 的 operationImpl()" << std::endl;
    }
};

class ConcreteImplementorB : public Implementor {
public:
    void operationImpl() override {
        std::cout << "ConcreteImplementorB 的 operationImpl()" << std::endl;
    }
};

在main函数中,我们可以根据需要为Abstraction实例化不同的Implementor对象,从而达到在运行时动态改变系统行为的目的,这就是桥接模式的关键所在。通过这种方式,抽象与实现得以解耦,各自可以独立扩展而不影响对方。

进一步阐述桥接模式的优点和适用场景

优点:

  1. 松耦合:桥接模式使得抽象和实现能够独立地变化和发展,提高系统的可扩展性。
  2. 灵活性:由于抽象部分和实现部分被彻底分开,因此可以根据需要组合不同的抽象和实现,增强了系统的灵活性。
  3. 避免多重继承:在某些情况下,如果采用传统的继承机制,可能会导致类层次过深或出现菱形继承问题,桥接模式则可以有效地避免这些问题,通过组合而非继承来实现复用。

适用场景:

  1. 系统需要在多个维度上进行变化:例如,操作系统既有GUI版又有命令行版,GUI版又支持多种窗口系统,这时就可以使用桥接模式把操作系统核心与用户界面和窗口系统分离开来。
  2. 希望在运行时切换实现:例如,不同的数据库引擎有不同的实现,但是上层应用的查询语句是通用的,此时可以用桥接模式,在运行时根据需求切换数据库引擎。
  3. 一个类存在两个独立变化的维度,且这两个维度需要进行组合:例如打印机既可以打印黑白也可以打印彩色,打印目标既可以是纸张也可以是PDF,这时就可以使用桥接模式将颜色模式和输出格式解耦。

总结来说,桥接模式在设计中鼓励关注点分离,让抽象和实现各自独立演进,提高了代码的可维护性和复用性。在实际编程过程中,尤其是在设计复杂的面向对象系统时,合理运用桥接模式可以显著提升软件的设计质量。

桥接模式的实际应用场景还包括但不限于以下几种情况:

  1. 图形界面库:图形界面库通常有多种外观(如按钮、菜单等)和多种平台实现(Windows、Mac、Linux等)。桥接模式可以使抽象外观接口独立于各个平台的具体实现,方便在不同平台上复用相同的外观设计。

  2. 日志系统:日志系统可能需要支持不同的日志级别(如Debug、Info、Error等)和不同的输出目的地(如控制台、文件、数据库等)。桥接模式可以将日志级别抽象出来,同时将输出目的地作为一个独立的维度,使得日志系统可以在不修改原有代码的基础上轻易更换日志级别或输出目的地。

  3. 数据库驱动:数据库驱动程序可能需要支持不同的数据库(MySQL、Oracle、SQL Server等)和不同的操作(查询、插入、删除、更新等)。桥接模式可以将数据库操作抽象成统一的接口,而具体的数据库操作由不同的实现类负责,这样就能灵活地替换或升级数据库驱动。

  4. 图像处理库:图像处理库可能需要支持多种图像格式(JPEG、PNG、GIF等)和多种处理操作(缩放、旋转、裁剪等)。桥接模式可以将图像处理操作抽象化,并与各种图像格式的读写实现解耦,便于添加新的格式支持或处理功能。

总之,桥接模式在面对抽象和实现之间需要独立扩展的问题时,能够帮助我们构建更加灵活、易于维护和扩展的设计方案。在实际开发中,识别出可能需要桥接模式的场景并正确运用,能够显著提升系统的可维护性和可扩展性。

另外,桥接模式也适用于以下情况:

  1. 网络通信框架:在网络通信框架中,抽象接口可以定义诸如发送消息、接收消息等功能,而具体实现可以包括TCP、UDP、WebSocket等多种协议。这样,上层应用只需关注消息的发送和接收逻辑,而无需关心底层通信协议的具体实现。

  2. 多语言本地化:在国际化应用中,可以将界面的逻辑(如按钮、标签、提示信息等)与具体语言环境(如英文、中文、法文等)分离,通过桥接模式使得在切换不同语言环境时,仅需替换具体的本地化实现即可。

  3. 硬件驱动程序:对于硬件设备(如打印机、扫描仪等),抽象接口可以定义一系列设备操作,而具体实现可以针对不同的厂商和型号。这样,即使更换了硬件设备,只要新设备遵循同一接口规范,应用也能无缝对接。

  4. 支付系统:支付系统可能需要对接多种支付渠道(如支付宝、微信支付、银行卡支付等),并且每种支付渠道的操作流程各不相同。桥接模式可以将支付操作抽象化,而将具体支付渠道的处理逻辑放在各自的实现类中。

桥接模式不仅限于以上场景,它强调的是将抽象部分与实现部分相分离,使其可以独立变化。在软件工程实践中,遇到类似的多维度变化需求时,都应该考虑是否可以采用桥接模式进行设计。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Arduino与processing之间的通信——进阶版

本次需要实现Arduino获取板子的偏转角度并通过串口发送给processing&#xff0c;processing部分根据传输过来的各个轴的偏转角度建立对应偏转角度的3D模型。 这就涉及了两个轴正负方向的偏转&#xff0c;我的实现思路是使用串口传输 字母数字 格式的信息&#xff0c;字母用来判…

Corel 会声会影 2023 激活码 会声会影 2023 序列号生成器

会声会影 2023 已经出来很长时间了&#xff0c;但是对它的热爱一直持续不减&#xff0c;今天我给大家带来2023版本为用户带来的多个全新功能&#xff0c;可以更好的编辑视频&#xff0c;不过软件还是付费的&#xff0c;为此我带来了会声会影 2023序列号生成器&#xff0c;可以轻…

算法沉淀——动态规划之01背包问题(leetcode真题剖析)

算法沉淀——动态规划之01背包问题 01.【模板】01背包02.分割等和子集03.目标和04.最后一块石头的重量 II 01背包问题是一类经典的动态规划问题&#xff0c;通常描述为&#xff1a;有一个固定容量的背包&#xff0c;以及一组物品&#xff0c;每件物品都有重量和价值&#xff0c…

【蓝桥杯】分巧克力

一.题目描述 二.输入描述 三.输出描述 四.问题分析 //分巧克力 #include <iostream> #include <algorithm>using namespace std;const int N1e510; int n,k,h[N],w[N];bool judge(int mid){int cnt0;for(int i0;i<n;i){cnt(h[i]/mid)*(w[i]/mid);if(cnt>k)r…

【短时交通流量预测】基于Elman神经网络

课题名称&#xff1a;基于Elman神经网络的短时交通流量预测 版本时间&#xff1a;2023-04-27 代码获取方式&#xff1a;QQ&#xff1a;491052175 或者 私聊博主获取 模型简介&#xff1a; 城市交通路网中交通路段上某时刻的交通流量与本路段前几个时段的交通流量有关&#…

数仓项目6.0(一)

尚硅谷大数据项目【电商数仓6.0】企业数据仓库项目_bilibili 数据流转过程 用户➡️业务服务器➡️数据库存储➡️数仓统计分析➡️数据可视化 数据仓库处理流程&#xff1a;数据源➡️加工数据➡️统计筛选数据➡️分析数据 数据库不是为了数据仓库服务的&#xff0c;需要…

【牛客】VL63 并串转换

题目 描述 题目描述&#xff1a; 设计一个模块进行并串转换&#xff0c;要求每四位d输为转到一位dout输出&#xff0c;输出valid_in表示此时的输入有效 信号示意图&#xff1a; clk为时钟 rst为低电平复位 valid_in 表示输入有效 d 信号输入 dout 信号输出 波形示意图&…

TypeError: the JSON object must be str, bytes or bytearray, not dict

参考文章&#xff1a;https://blog.csdn.net/yuan2019035055/article/details/124934362 Python基础系列&#xff08;一&#xff09;搞懂json数据解析与字典之间的关系 代码&#xff1a; 报错信息: TypeError: the JSON object must be str, bytes or bytearray, not dict …

光伏并网逆变器低电压穿越控制Simulink模型!

适用平台&#xff1a;MatlabSimulink 简介 当电网突发跌落故障时&#xff0c;电网电压降低会使并网电流增大、母线电压升高。当跌落程度较轻时&#xff0c;并网电流仍在逆变器安全运行的范围内&#xff1b;但跌落程度较深时&#xff0c;会引发逆变器过流和母线过压等问题&…

CommandLineRunner的使用

背景 在项目启动时需要做一些数据预加载或者某些操作&#xff0c;需要怎么办呢&#xff0c;方法其实有好几种&#xff0c;这里主要讲一下SpringBoot提供的CommandLineRunner接口的使用。一、案例说明以及实现 1.实现CommandLineRunner接口 定义一个类实现CommandLineRunner接…

在 Linux 上用 zram 替代传统交换空间 | Linux 中国

我在我的电脑上花了很多时间&#xff08;我是说工作&#xff09;&#xff0c;我发现了很多有趣的东西。其中最近引起我注意的是 zram0 设备。我是在几个月前写一篇文章时第一次注意到它&#xff0c;它显示在 lsblk 命令的输出中&#xff1a; # lsblk NAME MAJ:MIN RM…

Mybatis-Plus介绍

目录 一、Mybatis-Plus简介 1.1、介绍 1.2、特性 1.3、架构 1.4、Mybatis-Plus与Mybatis的区别 二、快速入门 2.1、首先创建数据库mybatis-plus 2.2、创建user表 2.3、插入数据 2.4、创建Spring-Boot项目 2.5、添加依赖 2.6、连接数据库 一、Mybatis-Plus简介 1.1、…

内网穿透的应用-如何修改Nginx服务location代理转发规则结合cpolar实现无公网ip环境访问内网站点

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

北京大学发布,将试错引入大模型代理学习!

引言&#xff1a;探索语言智能的新边界 在人工智能的发展历程中&#xff0c;语言智能始终是一个核心的研究领域。随着大语言模型&#xff08;LLM&#xff09;的兴起&#xff0c;我们对语言智能的理解和应用已经迈入了一个新的阶段。这些模型不仅能够理解和生成自然语言&#x…

什么是杠杆?WeTrade众汇这样举例,大家都明白

杠杆是投资交易者一定要知道的一个金融术语。那么什么是杠杆呢?下面WeTrade众汇就用苹果进行举例&#xff0c;大家就都会明白&#xff0c;原来如此简单。 发挥我们投资者的想象&#xff0c;我们现在要进行一场苹果的买卖&#xff0c;能够赚钱的本质就是高买低卖&#xff0c;所…

快速搭建Vue前端框架

快速搭建Vue前端框架 安装Vue Vue官方安装过程:https://cli.vuejs.org/zh/guide/installation.html 二.创建Vue工程 2.2 安装淘宝镜像 安装淘宝镜像&#xff08;会让你安装Vue的速度加快&#xff09;&#xff1a; npm config set registry https://registry.npm.taobao.or…

Java进阶(锁)——锁的升级,synchronized与lock锁区别

目录 引出Java中锁升级synchronized与lock锁区别 缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 Java进阶&#xff08;锁&#xff09;——锁的升级&#xff0c;synchronized与lock锁区别 Java中锁升级 看一段代码&#xff1a; public class…

IDE插件-通义灵码-用AI写代码

安装tongyi插件 右边就出现这个插件了&#xff0c;用支付宝账号登录成功后就出现一个AI机器人了 选中代码右键就能看到他的常规功能 提问模式 智能代码联想&#xff0c;根据你上一句代码&#xff0c;点回车&#xff0c;等一会&#xff0c;自动给你下语句想要的代码&#xff0c;…

【毕业论文小记】从Peer下载到近断层脉冲地震动生成——基于一个完全免费的地震波生成Python程序

如果因为TA和游戏相关关注我的朋友们&#xff0c;看到这篇可以不用继续往下看了啊啊啊啊&#xff01;不是跑路了不是跑路了&#xff01;毕业论文需要&#xff08;本专业土木人的心酸&#xff09;&#xff01;&#xff01; 在写毕业论文的时候&#xff0c;进行近断层脉冲地震动…

cleanmymacX破解版2024最新版下载

摘要 对于很多Mac用户来说&#xff0c;知您网分享的CleanMyMac X Mac破解版是大家首选的优秀Mac清理软件。由于它强大的功能&#xff0c;让大量新老用户所折服。作为老牌开发商制作的优秀应用&#xff0c;CleanMyMac X破解版几乎满足用户所有的清理需求。这款清理软件不仅包含…