【19】c++设计模式——>桥接模式
桥接模式的定义
C++的桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使得它们可以独立地变化。桥接模式的核心思想是利用组合关系代替继承关系,将系统划分成多个独立的、功能不同的类层次结构,并通过桥接类将它们连接起来。
在桥接模式中,有两个重要的概念:抽象化(Abstraction)和实现化(Implementation),它们分别对应了系统的抽象部分和实现部分。抽象化负责定义接口,并维护一个指向实现化对象的指针;实现化则负责定义具体的实现方法。
使用场景
关于桥接模式的使用对应的场景有很多,比如:
1.空调、电视等和他们对应的遥控器:空调、电视机是抽象,遥控器是实现;
2.手机品牌和手机软件:手机品牌是抽象,手机软件是实现;
3.跨品台的GUI在不同平台上运行:程序的GUI层是抽象,操作系统API是实现。
4.假设我们正在开发一个图形绘制应用程序,支持多种图形和不同的绘制渲染方式。其中,图形包括圆形、矩形等,渲染方式包括使用直线绘制、使用虚线绘制等。这两个维度的变化都可能会在未来进行扩展和修改。
就是说将具体的图形和具体的渲染桥接在一起,实现图形和渲染方式之间的解耦,我们可以在客户端代码中使用桥接模式,通过实例化具体的图形对象和具体的渲染实现对象,将它们桥接在一起,并进行绘制:
#include <iostream>// Abstract Render API
class RenderAPI {
public:virtual void renderCircle() = 0; // 抽象的渲染圆形方法virtual void renderRectangle() = 0; // 抽象的渲染矩形方法
};// Concrete Line Renderer
class LineRenderer : public RenderAPI {
public:void renderCircle() override {std::cout << "Render Circle with lines." << std::endl; // 使用线条渲染圆形}void renderRectangle() override {std::cout << "Render Rectangle with lines." << std::endl; // 使用线条渲染矩形}
};// Concrete Dashed Line Renderer
class DashedLineRenderer : public RenderAPI {
public:void renderCircle() override {std::cout << "Render Circle with dashed lines." << std::endl; // 使用虚线渲染圆形}void renderRectangle() override {std::cout << "Render Rectangle with dashed lines." << std::endl; // 使用虚线渲染矩形}
};// Abstract Shape
class Shape {
protected:RenderAPI* renderAPI;public:Shape(RenderAPI* api) : renderAPI(api) {}virtual void draw() = 0; // 抽象的绘制方法,具体的形状类将实现这个方法
};// Concrete Circle
class Circle : public Shape {
public:Circle(RenderAPI* api) : Shape(api) {}void draw() override {renderAPI->renderCircle(); // 调用渲染API的渲染圆形方法来绘制圆形}
};// Concrete Rectangle
class Rectangle : public Shape {
public:Rectangle(RenderAPI* api) : Shape(api) {}void draw() override {renderAPI->renderRectangle(); // 调用渲染API的渲染矩形方法来绘制矩形}
};int main() {// 创建一个圆形对象,并设置使用线条渲染的渲染APIShape* circleShape = new Circle(new LineRenderer());// 创建一个矩形对象,并设置使用虚线渲染的渲染APIShape* rectangleShape = new Rectangle(new DashedLineRenderer());// 绘制圆形circleShape->draw();// 绘制矩形rectangleShape->draw();delete circleShape;delete rectangleShape;return 0;
}
海贼王实例
对于海贼王中来说,有海军,有海贼团,不论是海军还是海贼团,他们都有自己的船,海军的船叫军舰,海贼团的船叫海贼船,因此,我们需要将船和团队分开;
船+海贼团 -->海贼船
船+海军—>军舰
对于一个海贼团或者一支海军部队来说,光有船是不完整的,船只是这个团队的抽象,如果想要让它鲜活起来就必要要有由人组成的团队,也就是抽象的具体实现。所以,在这个抽象类中包含了一个团队对象,船和团队二者之间的关系可以看做是聚合关系。
我们以草帽海贼团和斯摩格海贼团为例:
#include <iostream>
#include<string>
#include<map>
using namespace std;//不论是哪艘船上的船员肯定都是由一些个人的身份信息,为了将这些信息记录下来,先定一个存储数据的类:
//人员信息
struct Person
{Person(string name, string job, string ability, string reward, string beizhu=string()){this->name = name;this->job = job;this->ability = ability;this->reward = reward;this->beizhu = beizhu;}~Person(){cout << name << "被析构了..." << endl;}string name; //姓名string job; //工作string ability; //能力string reward; //赏金string beizhu; //备注
};
//关于团队的成员组成可以是海贼,也可以是海军,所以先定义一个团队的抽象类
class AbstractTeam
{
public:AbstractTeam(string name):m_teamName(name) {}//获取团队姓名string getTeamName(){return m_teamName;}//给团队添加成员,用map保存,键是姓名,值是Person类void addMember(Person* p){m_infoMap.insert(make_pair(p->name,p));}//打印成员信息void show(){cout << m_teamName << ":" << endl;//遍历mapfor(const auto & item:m_infoMap){cout << "【Name: " << item.second->name<< ", Job: " << item.second->job<< ", Ability: " << item.second->ability<< ", MoneyReward: " << item.second->reward<< ", BeiZhu: " << item.second->beizhu<< "】" << endl;}}//执行任务函数,海军和海贼的任务不同,因此是纯虚函数,子类中重写virtual void executeTask() = 0;//虚析构函数,释放类时,将m_infoMap保存的团队所有成员都析构掉virtual ~AbstractTeam(){for (const auto& item : m_infoMap){delete item.second;}}
protected:string m_teamName = string();//该团队的所有成员map<string, Person*> m_infoMap;
};
//具体的团队类,路飞的草帽海贼团和斯摩格的海军团
//草帽海贼团
class CaoMaoTeam :public AbstractTeam
{
public:using AbstractTeam::AbstractTeam;//继承基类的构造函数,而不用子类重新实现相同的构造函数void executeTask() override{cout << "在海上冒险,找到 ONE PIECE 成为海贼王!" << endl;}
};
//斯摩格海军团队
class SmokeTeam :public AbstractTeam
{
public:using AbstractTeam::AbstractTeam;void executeTask()override{cout << "为了正义,先将草帽一伙一网打尽!!!" << endl;}
};
//船类
/*不论是海军还是海贼在大海上航行都需要船,虽然他们驾驶的船只不同,
但是有很多属性还是一致的,所以我们可以先定义一个船的抽象类*/
class AbstructShip
{
public:AbstructShip(AbstractTeam* team) :m_team(team) {} //团队+船void showTeam(){m_team->show();m_team->executeTask();}virtual string getName() = 0;virtual void feature() = 0; //纯虚函数描述船的特点,在不同的子类中都需要重写virtual~AbstructShip() {}
protected:AbstractTeam* m_team = nullptr; //这里将团队和船绑定在一起了
};
//梅丽号
class Merry :public AbstructShip
{
public:using AbstructShip::AbstructShip;string getName() override{return string("前进梅丽号");}void feature()override{cout << getName() << "--船首为羊头,在司法岛化身船精灵舍己救下草帽一伙" << endl;}
};
//海军无敌战舰
class HaiJunJian :public AbstructShip
{
public:using AbstructShip::AbstructShip;string getName()override{return string("无敌海军号");}void feature() override{cout << getName() << " -- 船底由海楼石建造, 可以穿过无风带的巨大炮舰!" << endl;}
};
int main()
{//草帽海贼团CaoMaoTeam* caomao = new CaoMaoTeam("草帽海贼团");Person* luffy = new Person("路飞", "船长", "橡胶果实能力者", "30亿贝里", "爱吃肉");Person* zoro = new Person("索隆", "剑士", "三刀流", "11亿1100万贝里", "路痴");Person* sanji = new Person("山治", "厨师", "隐形黑", "10亿3200万贝里", "好色");Person* nami = new Person("娜美", "航海士", "天候棒+宙斯", "3亿6600万贝里", "喜欢钱");caomao->addMember(luffy);caomao->addMember(zoro);caomao->addMember(sanji);caomao->addMember(nami);Merry* sunny = new Merry(caomao);sunny->feature();sunny->showTeam();//斯摩格SmokeTeam* smoke = new SmokeTeam("斯摩格海军团");Person* smoker = new Person("斯摩格", "中将", "冒烟果实能力者", "", "爱吃烟熏鸡肉");Person* dasiqi = new Person("达斯琪", "大佐", "一刀流", "", "近视");smoke->addMember(smoker);smoke->addMember(dasiqi);HaiJunJian* ship = new HaiJunJian(smoke);ship->feature();ship->showTeam();delete caomao;delete sunny;delete smoke;delete ship;return 0;}
相关文章:

【19】c++设计模式——>桥接模式
桥接模式的定义 C的桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使得它们可以独立地变化。桥接模式的核心思想是利用组合关系代替继承关系,将系统划分成多个独立的、功能不同的类层次结…...

网络安全:六种常见的网络攻击手段
1、什么是VPN服务? 虚拟专用网络(或VPN)是您的设备与另一台计算机之间通过互联网的安全连接。VPN服务可用于在离开办公室时安全地访问工作计算机系统。但它们也常用于规避政府审查制度,或者在电影流媒体网站上阻止位置封锁&#…...

使用HbuilderX运行uniapp中小程序项目
下载HbuilderX,下载链接: HBuilderX-高效极客技巧 导入相关项目。下载微信开发者工具。使用微信开发者工具打开:注意:如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需…...

基于PHP的水果商城网站,mysql数据库,前台+后台,原生PHP,PHP study(小皮),完美运行,有一万字报告。
目录 演示视频 基本介绍 论文目录 购买流程 系统截图 演示视频 基本介绍 基于PHP的水果商城网站,mysql数据库,前台后台,原生PHP,PHP study(小皮),完美运行,有一万字报告。 前…...

【uniapp】自定义导航栏时,设置安全距离,适配不同机型
1、在pages.json中,给对应的页面设置自定义导航栏样式 {"path": "pages/index/index","style": {"navigationStyle": "custom","navigationBarTextStyle": "white","navigationBarTitl…...
JAVA经典百题之数组逆序输出
题目:将一个数组逆序输出。 程序分析 要将一个数组逆序输出,即将数组中的元素顺序颠倒过来,可以使用多种方法。基本思路是创建一个新数组或修改原数组,将元素的顺序颠倒。 方法1: 创建新数组实现 思路 创建一个新的数组,长度…...
vue run dev 配置nginx
由于项目有多个vue项目,在开发过程中需要联调,而不是每次发布后再联调. 比如有2个项目: main-project(主项目),test1-project. 由于是多项目,每个项目相当于有一个独立的域,这里test1-project设置域名称为test1 vue修改 在vite.config.ts中配置一个base:"/test1/"…...
Python实现RNN算法对MFCC特征的简单语音识别
Python实现RNN算法对MFCC特征的简单语音识别 1、实现步骤 借助深度学习库 TensorFlow/Keras 来构建模型 1.对标签进行编码,将文本标签转换为整数标签。 2.对 MFCC 特征数据进行填充或截断,使其长度一致,以便于输入到 RNN 模型中 3.如果是二维数据需要转成三维: Simpl…...

借助PLC-Recorder,汇川中型PLC(AM、AC系列,CODESYS平台)2ms高速采集的方法
高速数据采集要保证速度,也要保证时刻的准确性。在windows系统里,时间稳定性是个很难的问题。如果PLC发送的数据里带有时间信息,则可以由PLC来保证采样周期的稳定性。 从V2.12版本开始,PLC-Recorder软件可以处理发送电文里的时间…...

vscode package.json文件开头的{总是提升警告
警告如下 Problems loading reference https://json.schemastore.org/stylelintrc.json: Unable to load schema from https://json.schemastore.org/stylelintrc.json: read ECONNRESET. 解决如下 在设置(settings.json)里 新增一条属性 "ht…...

$attrs 和 $listeners (vue2vue3)
目录 透传 Attributes Attributes 继承 对 class 和 style 的合并 v-on 监听器继承 深层组件继承 禁用 Attributes 继承 多根节点的 Attributes 继承 vue2 $attrs 和 $listeners $attrs 概念说明 $attrs 案例 $listeners 概念说明 $listeners案例 vue3 $attr…...

嵌入式系统中的加密性能:第2部分
本系列的第1部分讨论了影响系统级密码性能的硬件和软件变量。现在,在第2部分中,我们将重点介绍两种用于测量高级后备加速器性能的方法:1)驱动器级加速器测试以识别加速器或SoC内存带宽约束,以及2)应用程序/…...

STM32F103 最小系统 PCB 设计与原理
这篇文章是来自我学习: 带着你从手册开始画板 STM最小系统板教程系列(一)_哔哩哔哩_bilibili 这套教程的笔记,同时本文中也参考了其他教程以及我遇到的困惑与自答,最终汇总。 一、单片机最小系统 单片机最小系统是由…...
JVM篇---第十一篇
系列文章目录 文章目录 系列文章目录一、如何选择垃圾收集器?二、什么是类加载器?三、什么是 tomcat 类加载机制?一、如何选择垃圾收集器? 如果你的堆大小不是很大(比如 100MB ),选择串行收集器一般是效率最高的。 参数: -XX:+UseSerialGC 。如果你的应用运行在单核的机…...

MongoDB——window11安装mongodb5.0.21版本服务端(图解版)
目录 一、mongodb官网下载地址二、安装步骤三、配置环境变量四、运行mongodb 一、mongodb官网下载地址 mongodb官网下载地址:https://www.mongodb.com/try/download/community 二、安装步骤 双击运行下载好的mongodb-windows-x86_64-5.0.21-signed.msi安装包&am…...
第1次 更多的bash shell命令
1.检测程序 程序都是进程在运行,进程里面有很多线程,面试经常会问进程和线程的区别,线程可以访问另一个线程的什么什么的,这些我都听腻了,区别就是进程会分配程序需要的空间,创建线程需要的资源,…...

工业路由器项目应用(4g+5g两种工业路由器项目介绍)
引言: 随着工业智能化的不断发展,工业路由器在各个领域的应用越来越广泛。本文将介绍两个工业路由器项目的应用案例,一个是使用SR500 4g工业路由器,另一个是使用SR800 5g工业路由器。 详情:https://www.key-iot.com/i…...

国产开源无头CMS,MyCms v4.7 快捷生成接口开发后台
MyCms 是一款基于 Laravel 开发的开源免费的开源多语言商城 CMS 企业建站系统。 MyCms 基于 Apache2.0 开源协议发布,免费且可商业使用,欢迎持续关注我们。技术交流 QQ 群:887522124 加群请备注来源:如gitee、github、官网等 v4…...

C++(反向迭代器)
前言: 上一章我们介绍了适配器,也提了一下迭代器适配器,今天我们就从反向迭代器把迭代器适配器给解释一下。 既然 都叫迭代器容器了 就说名只要接口合适他可以封装实现各种容器需求包括vector list 。 目录 1.反向迭代器设计 1.1反向迭代…...

DataX和dataX-web 集群部署及使用
📑 DataX和dataX-web 集群部署及使用 一 . 安装前准备 DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 DataX 采用 框架 插件 的模式…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...