桥接模式(Bridge)

news2024/12/23 9:10:28

定义

桥接是一种结构型设计模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而能在开发时分别使用。

前言

1. 问题

假如你有一个几何形状(Shape)类, 从它能扩展出两个子类: 圆形(Circle)和方形(Square)。你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为红色(Red)和蓝色(Blue)的形状子类。但是,由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合,例如蓝色圆形(BlueCircle)和红色方形(RedSquare)。

在层次结构中新增形状和颜色将导致代码复杂程度指数增长。例如添加三角形状,你需要新增两个子类,也就是每种颜色一个;此后新增一种新颜色需要新增三个子类,即每种形状一个。如此以往,情况会越来越糟糕。

2. 解决方案

问题的根本原因是我们试图在两个独立的维度——形状与颜色——上扩展形状类。这在处理类继承时是很常见的问题。

桥接模式通过将继承改为组合的方式来解决这个问题。具体来说,就是抽取其中一个维度并使之成为独立的类层次,这样就可以在初始类中引用这个新层次的对象,从而使得一个类不必拥有所有的状态和行为。

根据该方法,我们可以将颜色相关的代码抽取到拥有红色和蓝色两个子类的颜色类中,然后在形状类中添加一个指向某一颜色对象的引用成员变量。现在,形状类可以将所有与颜色相关的工作委派给连入的颜色对象。这样的引用就成为了形状和颜色之间的桥梁。此后,新增颜色将不再需要修改形状的类层次,反之亦然。

结构

  1. 抽象部分(Abstraction)提供高层控制逻辑, 依赖于完成底层实际工作的实现对象。
  2. 实现部分(Implementation)为所有具体实现声明通用接口。抽象部分仅能通过在这里声明的方法与实现对象交互。抽象部分可以列出和实现部分一样的方法,但是抽象部分通常声明一些复杂行为,这些行为依赖于多种由实现部分声明的原语操作。
  3. 具体实现(Concrete Implementations)中包括特定于平台的代码。
  4. 精确抽象(Refined Abstraction)提供控制逻辑的变体。与其父类一样,它们通过通用实现接口与不同的实现进行交互。
  5. 通常情况下,客户端(Client)仅关心如何与抽象部分合作。但是,客户端需要将抽象对象与一个实现对象连接起来。

适用场景

  • 如果你想要拆分或重组一个具有多重功能的庞杂类(例如能与多个数据库服务器进行交互的类),可以使用桥接模式。

类的代码行数越多,弄清其运作方式就越困难,对其进行修改所花费的时间就越长。一个功能上的变化可能需要在整个类范围内进行修改,而且常常会产生错误,甚至还会有一些严重的副作用。桥接模式可以将庞杂类拆分为几个类层次结构。此后,你可以修改任意一个类层次结构而不会影响到其他类层次结构。这种方法可以简化代码的维护工作,并将修改已有代码的风险降到最低。

  • 如果你希望在几个独立维度上扩展一个类,可使用该模式。

桥接建议将每个维度抽取为独立的类层次。初始类将相关工作委派给属于对应类层次的对象,无需自己完成所有工作。

  • 如果你需要在运行时切换不同实现方法,可使用桥接模式。

当然并不是说一定要实现这一点,桥接模式可替换抽象部分中的实现对象,具体操作就和给成员变量赋新值一样简单。顺便提一句,最后一点是很多人混淆桥接模式和策略模式的主要原因。记住,设计模式并不仅是一种对类进行组织的方式,它还能用于沟通意图和解决问题。

实现

  1. 明确类中独立的维度。独立的概念可能是:抽象/平台,域/基础设施,前端/后端或接口/实现。
  2. 了解客户端的业务需求,并在抽象基类中定义它们。
  3. 确定在所有平台上都可执行的业务。并在通用实现接口中声明抽象部分所需的业务。
  4. 为你域内的所有平台创建实现类,但需确保它们遵循实现部分的接口。
  5. 在抽象类中添加指向实现类型的引用成员变量。抽象部分会将大部分工作委派给该成员变量所指向的实现对象。
  6. 如果你的高层逻辑有多个变体,则可通过扩展抽象基类为个变体创建一个精确抽象。
  7. 客户端代码必须将实现对象传递给抽象部分的构造函数才能使其能够相互关联。此后,客户端只需与抽象对象进行交互,无需和实现对象打交道。

优点

  • 你可以创建与平台无关的类和程序。
  • 客户端代码仅与高层抽象部分进行互动,不会接触到平台的详细信息。
  • 开闭原则。你可以新增抽象部分和实现部分,且它们之间不会相互影响。
  • 单一职责原则。抽象部分专注于处理高层逻辑,实现部分处理平台细节。

缺点

对高内聚的类使用该模式可能会让代码更加复杂。

Abstraction.hpp

#ifndef B6338413_D95A_40E4_B915_FA2F8E721C93
#define B6338413_D95A_40E4_B915_FA2F8E721C93
#include <string>
#include "Implementation.hpp"
using namespace std;
class Pen{
    public:
        virtual draw(string name)=0;
        void set_color(Color *color){
            color_ = color;
        }
    protected:
        Color * color_;
};

#endif /* B6338413_D95A_40E4_B915_FA2F8E721C93 */

Implementation.hpp

#include "iostream"
#include <string>
using namespace  std;
class Color{

    public:
        virtual void bepaint(string pen_type,string name );
};

ConcreteImplementation.hpp:

#ifndef B8A280CC_C05F_48F0_9E2C_EB82CDABEB18
#define B8A280CC_C05F_48F0_9E2C_EB82CDABEB18

#include <string>
#include "Implementation.hpp"

class Red:public Color{
    public:
        void bepaint(std::string pen_type, std::string name) override {
            std::cout << pen_type << "红色的" << name << "." << std::endl;
        }
};
class Green : public Color {
    
    public:
        void bepaint(std::string pen_type, std::string name) override {
            std::cout << pen_type << "绿色的" << name << "." << std::endl;
        }
};

#endif /* B8A280CC_C05F_48F0_9E2C_EB82CDABEB18 */

RefinedAbstraction.hpp:

#ifndef AA4EBAC9_0D68_4963_A425_2CC40B042A2F
#define AA4EBAC9_0D68_4963_A425_2CC40B042A2F


#include <string>
#include "Abstraction.hpp"

// 精确抽象类: BigPen
class BigPen : public Pen {
 public:
    void draw(std::string name) {
        std::string pen_type = "大号钢笔绘制";
        color_->bepaint(pen_type, name);
    }
};

// 精确抽象类: SmallPencil
class SmallPencil : public Pen {
 public:
    void draw(std::string name) {
        std::string pen_type = "小号铅笔绘制";
        color_->bepaint(pen_type, name);
    }
};



#endif /* AA4EBAC9_0D68_4963_A425_2CC40B042A2F */

main.cpp 

#include "ConcreteImplementation.hpp"
#include "RefinedAbstraction.hpp"

int main() {
    // 客户端根据运行时参数获取对应的Color和Pen
    Color* color = new Red();
    Pen* pen = new SmallPencil();

    pen->set_color(color);
    pen->draw("太阳");

    delete color;
    delete pen;
}

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

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

相关文章

2023最强免费的AI生成图像工具其1

Midjourney虽然很强&#xff0c;但是要钱.Stable Diffusion也很强&#xff0c;但是对于小白来说部署起来也是很麻烦。我们整理了一些已经上线了的&#xff0c;可以直接访问和使用的AI生成图像的工具网站集合。 收录到 2023 最强免费AI生成图像工具集合系列https://www.webhub1…

STM32速成笔记—RTC

文章目录 一、RTC简介二、STM32的RTC2.1 主要特性2.2 RTC框图介绍 三、访问后备区域步骤四、RTC配置步骤五、RTC程序配置5.1 RTC结构体定义5.2 RTC初始化函数5.3 设置年月日&#xff0c;时分秒5.4 判断闰年函数5.5 获取当前年月日&#xff0c;时分秒5.6 获取星期几5.7 中断服务…

【②MySQL 】:测试数据准备、SQL语句规范与基本操作

前言 欢迎来到小K的MySQL专栏&#xff0c;本节将为大家准备MySQL测试数据、以及带来SQL语句规范、数据库的基本操作的详细讲解~✨文末送书&#xff0c;小K赠书活动第二期 目录 前言一、准备测试数据二、SQL语句规范三、数据库的基本操作四、总结&#xff1a;文末赠书 一、准备测…

智能应急疏散系统在大型建筑中的的功能与应用

安科瑞 华楠 摘 要&#xff1a;随着经济的不断发展和城市化进程的推进,城市建筑逐渐发展为高层化、大型化和功能综合化,大空间的建筑物增多。为了实现以人为本,坚持可持续发展理念,保证城市建设系统的正常运行,安全防灾系统在建筑中必不可少,而火患是一项重要的防范内容,要不断…

使用RabbitMQ死信队列关闭未支付的订单

一、什么是RabbitMQ死信队列 RabbitMQ死信队列&#xff08;Dead-Letter Exchange&#xff0c;简称DLX&#xff09;是一种特殊类型的交换机&#xff0c;用于处理在队列中无法被消费的消息。当消息无法被消费时&#xff0c;它会被转发到死信队列中&#xff0c;以便进一步处理。 …

7-WebApis-1

Web APIs - 1 掌握DOM属性操作&#xff0c;完成元素内容设置&#xff0c;元素属性设置&#xff0c;控制元素样式 DOM简介获取DOM元素操作元素内容操作元素属性定时器-间隔函数综合案例 描述属性/方法效果获取DOM对象document.querySelector()获取指定的第一个元素document.que…

nuxt 设置i18n后多语言文件不会动态更新

nuxt 设置i18n后多语言文件不会动态更新 昨天遇到的一个问题&#xff0c;然后研究了一整天&#xff0c;今天才得到解决 nuxt 设置i18n多语言时多语言文件不会动态更新 我的原始代码如下&#xff1a; {modules: [nuxtjs/i18n,],i18n: {locales: [{code: en,iso: en-US,name:…

构建可靠软件的关键步骤之单元测试

引言&#xff1a;在当今快节奏的软件开发环境中&#xff0c;构建可靠的软件是至关重要的。单元测试作为软件开发过程中的关键步骤之一&#xff0c;能够帮助开发者发现和解决代码中的错误&#xff0c;确保代码的正确性。本文将详细介绍单元测试的概念、重要性以及如何有效地进行…

impala远程连接失败排查

周一开发反馈在本地电脑上连接impala失败&#xff0c;怀疑是服务问题。测试后发现服务正常&#xff0c;故障也恢复了&#xff0c;就没追究&#xff0c;第二天又出现相似的故障。服务依然正常。怀疑是网络问题。联系网络同事排查。telnet通。网络负载也不是很高&#xff0c;搁置…

档案库房温湿度标准及措施【档案八防十防解决方案】

档案馆库房温湿度调控标准及相应的措施方案 档案库房是档案保管的基本条件&#xff0c;档案库房温湿度与保护档案&#xff0c;延长档案寿命有很大关系。 档案库房适宜温湿度标准为&#xff1a;温度14℃—24℃&#xff0c;相对湿度45&#xff05;一60 一、库房温湿度对档案的影响…

基于Arduino单片机超声波测距仪设计

文章目录 摘 要 1.课程设计任务 1.1课程设计题目 1.2设计的要求 2.设计总体方案 2.1初步设计方案 2.2各个单元电路的设计要求 2.3主要性能指标 2.4总体方案 3.单元模块设计 3.1显示模块 3.2超声波测距模块 3.3蜂鸣器模块 3.4电机模块 3.5 LED二极管模块 4.软件…

【三维编辑】Editing Conditional Radiance Fields 编辑条件辐射场

Editing Conditional Radiance Fields&#xff08;ICCV 2021&#xff09; 作者单位&#xff1a;Steven Liu, Xiuming Zhang, Zhoutong Zhang, Richard Zhang MIT, Adobe Research, CMU 代码地址&#xff1a;https://github.com/stevliu/editnerf 文章目录 摘要前言一、相关工作…

避雷器带电监测仪

一、产品特点&#xff1a; 本机采用大屏幕液晶显示&#xff0c;全中文菜单操作&#xff0c;使用简便高精度采样、处理电路&#xff0c;先进的付里叶谐波分析技术&#xff0c;确保数据更加可靠 仪器采用独特的高速磁隔离数字传感器直接采ji输入的电压、电流信号&#xff0c;保证…

HTML 全面入门教程:从基础到高级

目录 一、基本结构和标签1. HTML 文档结构2. 常用标签 二、表单和输入元素1. 表单标签&#xff08;<form>&#xff09;2. 输入元素3.实例 三、样式和布局1. 内联样式2. 内部样式表3. 外部样式表 四、多媒体和嵌入内容1. 图像2. 音频和视频3. 嵌入内容 五、语义化标签语义…

胎压计PCBA方案设计

汽车的出现极大的方便了人们的交通出行&#xff0c;随着经济社会的发展&#xff0c;人们生活水平显著提高&#xff0c;不少家庭都购买了汽车。但是车主们不仅要知道开车&#xff0c;更需要知道检测汽车胎压。气压计也称为胎压计&#xff0c;是一种检测胎压的测量仪器。电子产品…

RabbitMQ学习笔记6(小滴课堂)路由,主题模式

我们去修改我们的生产者代码&#xff1a; 我们去修改我们的消费者&#xff1a; 第一个节点&#xff1a; 我们还要去创建其它更多的节点&#xff1a; 这里第二个节点我们只绑定一个交换机队列。 我们去分别启动消费者和生产者&#xff1a; 我们可以看到第一个交换机只绑定了一…

Deepin 20.8 linux convert 一寸照 调整图片尺寸413x579 300dpi

原图 convert修改尺寸指令 convert 一寸照.jpg -resize 413x579 一寸照413x579.jpg 目标图 尺寸已调整&#xff0c;dpi太低了 图片高清修复 提升dpi https://github.com/microsoft/Bringing-Old-Photos-Back-to-Life 官方安装过程参考 Installation Clone the Synchron…

2023腾讯云国际站注册流程介绍-腾讯云国际代充

腾讯云是国内三大云服务商之一&#xff0c;为国内外多个应用程序提供服务器支持。腾讯云的产品比较全面&#xff0c;包括云数据库、 CDN、对象存储&#xff08;COS&#xff09;和高防服务器等&#xff0c;满足各种上云需求。 1.腾讯云区分国内站和国际站&#xff0c;并存在明显…

C# MVC 多图片上传预览

一.效果图&#xff1a; 开发框架&#xff1a;MVC&#xff0c;Layui 列表主界面这里就不展示了&#xff0c;可以去看看这篇文章&#xff1a;Layui项目实战&#xff0c;这里讲的是“上传Banner”界面功能&#xff1a; 其中包括&#xff0c;多文件上传&#xff0c;预览&#xff0c…

【Python】python进阶篇之文件操作

文件操作 编码格式 python3默认的文件编码就是UTF-8 以下内容来源于AI 编码格式是指将字符、符号、数字等信息转化为二进制形式以便计算机能够理解和处理的规则或标准。在计算机领域&#xff0c;常见的编码格式有 ASCII、Unicode、UTF-8 等。 ASCII&#xff08;American Stand…