桥接模式(Bridge)

定义

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

前言

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和PenColor* color = new Red();Pen* pen = new SmallPencil();pen->set_color(color);pen->draw("太阳");delete color;delete pen;
}

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

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

相关文章

UE5.1.1 C++从0开始(15.作业4个人作业分享)

教程链接&#xff1a;https://www.bilibili.com/video/BV1nU4y1X7iQ 好吧这个作业应该是之前写的&#xff0c;但是我发现我没写&#xff0c;后面我又回去自己写了一遍再看代码&#xff0c;感觉上大差不差&#xff0c;各位可以看着我的和老师的还有自己的对比下。 SBTService_…

8.10 TCP是如何实现可靠传输的

目录 TCP 最主要的特点 面向流的概念 Socket 有多种不同的意思 TCP是如何实现可靠传输的&#xff1f; A 如何知道 B 是否正确收到了 M1 呢&#xff1f; 确认丢失 确认迟到 连续 ARQ 协议 累计确认 TCP报文段的首部格式 TCP 最主要的特点 TCP 是面向连接的运输层协议&a…

自动化测试验证码tesseract安装以及python联调

前提 经常会遇到登录系统时候需要输入动态验证码的情况&#xff0c;但是自动化如何识别图片然后登陆系统&#xff1f; 需要用到pytesseract识别验证码图片以及PIL图像处理方法 import pytesseract from PIL import Image, ImageEnhance1、tesseract安装 OCR&#xff0c;即O…

高速电路设计系列分享-熟悉JESD204B(中)

目录 概要 整体架构流程 技术名词解释 技术细节 1.数据链路层 小结 概要 提示&#xff1a;这里可以添加技术概要 随着高速ADC跨入GSPS范围&#xff0c;与FPGA(定制ASIC)进行数据传输的首选接口协JESD204B。为了捕捉频率范围更高的RF频谱&#xff0c;需要宽带RFADC。在其推动下…

星辰秘典:探索Python项目的神秘力量——贪吃蛇

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;星辰秘典&#xff1a;探索Python项目的神秘力量 &#x1f433;专栏&#xff1a;web开发&#xff08;html css js&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主…

SSMP整合案例(9) 统一表现层数据返回格式

上文 SSMP整合案例(8) Restful开发表现层接口 我们就已经是把表现层的接口写完了 但是 我们会发现 现在前端人员拿到我们的数据 格式看着非常的乱 我们 数据库 添加 修改 删除 就是但数据的格式 一个 布尔值 查询 就是 查多个 一个集合 查询 全部 则就是 一个对象的格式 还有分…

Mysql进阶(三)之索引篇

文章目录 前言索引介绍1.什么是索引&#xff1f;2.优缺点3.什么时候需要 / 不需要索引&#xff1f;4.语法 索引底层结构1.Hash表2.BTree 索引分类1.按字段特性2.按物理存储3.按字段个数 索引优化1.SQL性能分析2.索引失效3.常见索引优化方法 前言 以面试题驱动索引的学习&#…

【Linux】硬链接 和 软链接

为了方便用户访问文件&#xff0c;Linux提供了一种称为连接&#xff08;link&#xff09;的机制&#xff0c;可以将一个文件或目录与另一个文件或目录建立关联&#xff0c;从而实现多个路径指向同一个文件或目录的效果。 一、概述二、硬链接和软链接详解2.1 硬链接2.11 硬链接的…

如何在小程序中引入使用vant框架

一、vant框架 vantUI框架常用于移动端页面组件的基础库构建&#xff0c;为了让用户获得更趋向于原生的体验&#xff0c;它是一种相当不错的方案选择。 关于这个框架&#xff0c;它不仅有适用于移动端vue脚手架的版本&#xff0c;同时还存在可以兼容小程序开发的webapp版本。在…

你知道什么是生成对抗网络吗

生成对抗网络&#xff08;GANs&#xff09;是一种深度学习模型&#xff0c;已经显示出在许多生成相关任务中的卓越性能。最近几年&#xff0c;越来越多的研究人员将注意力集中于 GAN 的隐空间属性&#xff0c;并提出了许多利用这些属性进行语义图像编辑的方法。然而&#xff0c…

虚幻引擎(UE5)-大世界分区WorldPartition教程(二)

文章目录 前言一、OFPA怎么用二、OFPA怎么用总结 上一篇&#xff1a;虚幻引擎(UE5)-大世界分区WorldPartition教程(一) 前言 在UE4版本中中&#xff0c;Actor是保存在关卡文件中的&#xff0c;也就是说&#xff0c;如果要编辑关卡中的某些Actor&#xff0c;需要签出关卡文件进…

炫技亮点 Websocket集群解决方案汇总

文章目录 问题方案方案一&#xff1a;~~Session共享~~&#xff08;不可行&#xff09;方案二&#xff1a;负载均衡器&#xff08;状态路由&#xff09;方案三&#xff1a;广播机制&#xff08;异步方式 - 建议&#xff09;方案四&#xff1a;路由转发&#xff08;同步方式&…