C++设计模式——Bridge桥接模式

一,桥接模式简介

桥接模式是一种结构型设计模式,用于将抽象与实现分离,这里的"抽象"和"实现"都有可能是接口函数或者类。

桥接模式让抽象与实现之间解耦合,使得开发者可以更关注于实现部分,调用者(Client)可以更关注于抽象部分。

桥接模式可以将一个复杂的类进行拆分为好几个类,开发者可以修改其中任意一个类的实现,而不影响其他类的正常运行,该模式可以降低代码的维护工作量,降低代码风险。

桥接模式的核心就是:抽象化(Abstraction)与实现化(Implementation)

抽象化:忽略一些细节,将具有共同特征的不同实体抽象为同一个对象。

实现化:为抽象化提供具体的逻辑和代码实现。

举个例子:

假设有一堆几何体,这些几何体有形状、颜色等特征,形状有:矩形、圆形,颜色有:红色、蓝色。

为了使用类来描述这些几何体,我们可以将他们抽象为四个子类:红色矩形,蓝色矩形,红色圆形,蓝色圆形。

按照以上方式,如果几何体还包含更多种类的形状和颜色,例如椭圆、绿色,那么这些特征通过排列组合产生的子类将会呈指数级增长。如果此时使用桥接模式,将会大大降低类与类之间的耦合,减少了开发期间的代码量。

对应UML类图:

桥接模式将继承关系改为组合关系,对于以上几何体的描述,我们使用一个类来描述几何体的矩形、圆形等形状,我们使用另一个类来描述几何体的红色、蓝色等颜色,最后将这两个类的实例进行组合。当需要改变类的颜色或形状的实现时,无需修改整个类的实现,只需要修改颜色或形状的实现即可。

对应UML类图:

二,桥接模式的结构

桥接模式主要涉及的类:
1. 抽象角色类:是一个类,定义了统一的对外接口,并定义了接口的组成结构,但是不包含接口对应的具体实现。
2. 具体实现类:是一个或多个类,该类包含了对抽象角色类的接口的具体代码实现。这些类可以根据需求变化而独立变化,且不会影响到其他类的功能。具体实现类与抽象角色类之间的关联方式采用的是组合而非继承。
3. 桥接类:充当了抽象角色类和具体实现类之间的桥梁,负责维护抽象角色类和具体实现类之间的关系,它允许客户端在运行时选择使用哪个具体实现类。
桥接模式的主要组件:
1.Abstraction:抽象类,提供统一的抽象接口。内部包含对Implementor类对象的引用。
2.RefinedAbstraction:扩充抽象类,有的教程里面称为"ExtendedAbstraction",Abstraction的子类,扩充Abstraction的抽象接口。
3.Implementor:实现类,提供了实现类的接口,这个接口的功能和以上的抽象接口不同。
4.ConcreteImplementor:提供了实现类的接口对应的代码逻辑。
桥接模式UML类图:

代码实现: 

#include <iostream>class Implementation {
public:virtual ~Implementation() {}virtual std::string newOperation() const = 0;
};class ConcreteImplementationA : public Implementation {
public:std::string newOperation() const override {return "ConcreteImplementationA: Here's the result on the platform A.\n";}
};
class ConcreteImplementationB : public Implementation {
public:std::string newOperation() const override {return "ConcreteImplementationB: Here's the result on the platform B.\n";}
};class Abstraction {
protected:Implementation* implementation_;public:Abstraction(Implementation* implementation) : implementation_(implementation) {}virtual ~Abstraction() {}virtual std::string doOperation() const {return "Abstraction: Base operation with:\n" +this->implementation_->newOperation();}
};class RefinedAbstraction : public Abstraction {
public:RefinedAbstraction(Implementation* implementation) : Abstraction(implementation) {}std::string doOperation() const override {return "RefinedAbstraction: Extended operation with:\n" +this->implementation_->newOperation();}
};void ClientCode(const Abstraction& abstraction) {std::cout << abstraction.doOperation();
}int main() {Implementation* implementation_1 = new ConcreteImplementationA;Abstraction* abstraction_1 = new Abstraction(implementation_1);ClientCode(*abstraction_1);std::cout << std::endl;delete implementation_1;delete abstraction_1;Implementation* implementation_2 = new ConcreteImplementationB;Abstraction* abstraction_2 = new RefinedAbstraction(implementation_2);ClientCode(*abstraction_2);delete implementation_2;delete abstraction_2;return 0;
}

运行结果: 

Abstraction: Base operation with:
ConcreteImplementationA: Here's the result on the platform A.RefinedAbstraction: Extended operation with:
ConcreteImplementationB: Here's the result on the platform B.

三,桥接模式的应用场景

系统组件升级:当需要为现有系统增加新功能或替换已有功能,但又不希望改变原有接口时。

跨平台应用开发:使用桥接模式来处理不同操作系统或硬件平台的差异,例如在移动端APP应用中,UI组件同时兼容ios和Android平台。

第三方插件开发:使用桥接模式开发出可支持多种第三方服务的组件,例如移动支付api。

API扩展:当API的功能需要被扩展,又希望保持原有API的稳定时,使用桥接模式可以隐藏实现细节。

四,桥接模式的优缺点

桥接模式的优点:

分离接口的抽象与实现部分。

替代了继承的实现方式,代码的可复用性更强。

桥接模式可以修改任意一个模块的功能实现而不影响整个系统。

可以向用户隐藏实现细节。

降低了类之间的依赖性。

代码的可维护性很强,可以根据需求灵活地更换实现模块。

桥接模式的缺点:

引入了额外的抽象层,使系统变得更复杂。

会额外增加系统的理解与设计难度。

接口调用增多,带来额外的性能开销。

五,代码实战

代码实战: 

生产不同颜色和不同车型的汽车

#include<iostream>
#include<string>using namespace std;class IColor
{
public:virtual string Color() = 0;
};class RedColor : public IColor
{
public:string Color(){return "of Red Color";}
};class BlueColor : public IColor
{
public:string Color(){return "of Blue Color";}
};class ICarModel
{
public:virtual string WhatIsMyType() = 0;
};class Model_A : public ICarModel
{IColor* _myColor;
public:Model_A(IColor *obj) :_myColor(obj){}string WhatIsMyType(){return "I am a Model_A " + _myColor->Color();}
};class Model_B : public ICarModel
{IColor* _myColor;
public:Model_B(IColor *obj) :_myColor(obj){}string WhatIsMyType(){return "I am a Model_B " + _myColor->Color();;}
};int main()
{IColor* red = new RedColor();IColor* blue = new BlueColor();ICarModel* modelA = new Model_B(red);ICarModel* modelB = new Model_A(blue);cout << "\n" << modelA->WhatIsMyType();cout << "\n" << modelB->WhatIsMyType() << "\n\n";delete red;delete blue;return 0;
}

运行结果:


I am a Model_B of Red Color
I am a Model_A of Blue Color

六,参考阅读

https://refactoring.guru/design-patterns/bridge

https://design-patterns.readthedocs.io/zh-cn/latest/structural_patterns/bridge.html

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

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

相关文章

[C++] 编译期间生成一个元素等差的std::initializer_list

前因 写编译器的时候需要一个常量英文字母表&#xff0c;懒得26个字母一个个打了&#xff0c;于是搓了个板子。 源代码 // c14 required #include <initializer_list> #include <type_traits>template <typename _Tp, _Tp first_elem, int item_number, type…

具有不确定性感知注意机制的肺结节分割和不确定区域预测| 文献速递-深度学习结合医疗影像疾病诊断与病灶分割

Title 题目 Lung Nodule Segmentation and UncertainRegion Prediction With an Uncertainty-Aware Attention Mechanism 具有不确定性感知注意机制的肺结节分割和不确定区域预测 01 文献速递介绍 肺结节分割在肺癌计算机辅助诊断&#xff08;CAD&#xff09;系统中至关重…

java Springboot网上音乐商城(源码+sql+论文)

1.1 研究目的和意义 随着市场经济发展&#xff0c;尤其是我国加入WTO &#xff0c;融入经济全球化潮流&#xff0c;已进入国内外市场经济发展新时期&#xff0c;音乐与市场联系越来越紧密&#xff0c;我国音乐和网上业务也进入新历史发展阶段。为了更好地服务于市场&#xff0…

Java与服务网格(Service Mesh):构建高效微服务架构

在微服务架构成为企业开发标准的今天&#xff0c;如何有效地管理众多微服务之间复杂的通信成为了一个挑战。服务网格作为一种解决方案&#xff0c;它通过提供一个专门的基础设施层来处理服务间通信&#xff0c;从而使得应用开发更加专注于业务逻辑而非通信细节。本文将介绍服务…

px转rem插件postcss-plugin-px2rem使用方法(浏览器缩放页面自适应)

px转rem插件postcss-plugin-px2rem使用方法&#xff08;浏览器缩放页面自适应&#xff09; 1. 常见屏幕自适应的布局 百分比布局rem布局css媒体查询在前端框架设计初期&#xff0c;应优先选择好页面布局方式 2. postcss-plugin-px2rem插件的使用 官网地址&#xff1a;https…

程序员应该具备什么职业素养?

程序员应该有什么职业素养&#xff1f; 作为一个程序员&#xff0c;拥有以下职业素养是非常重要的&#xff1a; 扎实的技术功底&#xff1a;作为程序员&#xff0c;首先要具备扎实的技术基础&#xff0c;包括编程语言、算法、数据结构等方面的知识&#xff0c;能够熟练地解决问…

WebForms Hashtable

WebForms Hashtable 概述 在Web开发领域,尤其是使用ASP.NET WebForms框架时,Hashtable是一个经常被用到的数据结构。Hashtable是.NET Framework中的一个集合类,它提供了键值对的存储方式,其中每个键都是唯一的,键用于快速访问其对应的值。本文将详细介绍Hashtable在ASP.…

利用CompletableFuture优化Java中的异步编程

在现代应用开发中&#xff0c;异步编程是提高应用性能和用户体验的关键技术之一。Java从1.8版本开始引入了CompletableFuture&#xff0c;它为编写非阻塞的异步代码提供了强大的工具。本文将详细介绍CompletableFuture的使用方法&#xff0c;并通过具体代码示例来展示如何在实际…

不想搭集群,直接用spark

为了完成布置的作业&#xff0c;需要用到spark的本地模式&#xff0c;根本用不到集群&#xff0c;就不想搭建虚拟机&#xff0c;hadoop集群啥的&#xff0c;很繁琐&#xff0c;最后写作业还用不到集群&#xff08;感觉搭建集群对于我完成作业来说没有什么意义&#xff09;&…

Cisco Packet Tracer实验(二)

二、用交换机构建 LAN 构建物件如下&#xff1a; 四个PC 两个交换机 一个Multi Switch多功能拓展控制器 连线必须是这个直线&#xff01;&#xff01;&#xff01;不是虚线 最后实现效果如下&#xff1a; 全部的线是绿的&#xff0c;就表示是通的。 尝试一下&#xff0c;看PC…

SolidWorks对设计电脑硬件配置要求是怎么样的

SolidWorks&#xff0c;作为达索系统&#xff08;Dassault Systemes&#xff09;旗下的子公司&#xff0c;一直以其出色的机械设计软件解决方案而著称。它是基于Parasolid内核开发&#xff0c;是单核三维设计软件&#xff0c;面上使用比较多的版本有SolidWorks2022、SolidWorks…

Golang | Leetcode Golang题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; func maxPoints(points [][]int) (ans int) {n : len(points)if n < 2 {return n}for i, p : range points {if ans > n-i || ans > n/2 {break}cnt : map[int]int{}for _, q : range points[i1:] {x, y : p[0]-q[0], p[1]-q[1]if…

解决vue项目路径用@报错问题,,

vue项目中不同文件src有的可以用来加载图片, 有的文件只能用相对路径../ , 很奇怪 一般vue项目框架下载下来,默认路径可以用 ,来替代相对路径 解决方法 清理缓存&#xff1a;删除node_modules目录下的.cache文件夹&#xff0c;或者使用IDE的清理缓存功能。 亲测有效 资料…

4. 案例研究-接口程序

4. 案例研究-接口程序 本章通过一个案例研究, 来展示设计互相配合的函数的过程.4.1 turtle 模块 创建一个文件mypolygon.py, 并输入如下代码:import turtle bob turtle.Turtle() print(bob)# 这一句的作用是让画板停留, 等手动点击x关闭画板, 程序才结束. # 否则程序执行完毕…

通用大模型与垂直大模型的博弈

在人工智能的蓬勃发展中&#xff0c;大模型正成为焦点&#xff0c;尤其是在通用大模型和垂直大模型之间的竞争中。通用大模型具有更广泛的应用场景&#xff0c;而垂直大模型则在特定领域中展现出更高的可能性和更快的普及速度。虽然目前谁能形成绝对优势尚无定论&#xff0c;但…

8.12 面要素符号化综述

文章目录 前言面要素介绍总结 前言 本章介绍如何使用矢量面要素符号化说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 面要素介绍 地理空间的要素分为点、线和面&#xff0c;对应的符号也分三类&#xff1a;Marker Symbol、Line Symbol和Fill Symbol&…

c#中上传超过30mb的文件,接口一直报404,小于30mb的却可以上传成功

在一次前端实现上传视频文件时,超过30mb的文件上传,访问接口一直报404,但是在Swagger中直接访问接口确是正常的,且在后端控制器中添加了限制特性,如下 但是却仍然报404,在apifox中请求接口也是报404, 网上说: 在ASP.NET Core中,配置请求过来的文件上传的大小限制通常…

【Android面试八股文】为什么Android中要设计为只能在UI线程中去更新UI?Android中子线程真的不能更新UI吗?如何在子线程中更新UI?

文章目录 一、Android为什么不能在子线程更新UI?二、为什么Android中要设计为只能在UI线程中去更新UI?三、如果不在UI线程中更新UI,可能会出现什么问题呢?四、ViewRootImp是在onActivityCreated方法后面创建的吗?五、为什么一开始在Activity的onCreate方法中创建一个子线程…

生命在于学习——Python人工智能原理(3.4)

三、深度学习 7、过拟合与欠拟合 过拟合和欠拟合是所有机器学习算法都要考虑的问题。 &#xff08;1&#xff09;基本定义 a、欠拟合 欠拟合是指机器学习模型无法完全捕获数据集中的复杂模式&#xff0c;导致模型在新数据上的表现不佳&#xff0c;这通常是由于模型过于简单…

C++进阶,一文带你彻底搞懂左右值引用以及移动语义和完美转发!

目录 一、左值引用1.左值2.左值引用3.左值引用的用途&#xff08;1&#xff09;修改实参&#xff08;2&#xff09;减少拷贝&#xff08;3&#xff09;使用左值引用可以在外部修改对象内的成员变量的值 二、右值引用1.右值&#xff08;1&#xff09;纯右值&#xff08;2&#x…