【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 采用 框架 插件 的模式…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
Git 命令全流程总结
以下是从初始化到版本控制、查看记录、撤回操作的 Git 命令全流程总结,按操作场景分类整理: 一、初始化与基础操作 操作命令初始化仓库git init添加所有文件到暂存区git add .提交到本地仓库git commit -m "提交描述"首次提交需配置身份git c…...

英国云服务器上安装宝塔面板(BT Panel)
在英国云服务器上安装宝塔面板(BT Panel) 是完全可行的,尤其适合需要远程管理Linux服务器、快速部署网站、数据库、FTP、SSL证书等服务的用户。宝塔面板以其可视化操作界面和强大的功能广受国内用户欢迎,虽然官方主要面向中国大陆…...
STL 2迭代器
文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器? 1.迭代器…...