设计模式- 桥接模式(Bridge Pattern)结构|原理|优缺点|场景|示例

                                    设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)       策略模式        模板方法模式        观察者模式        迭代器模式        责任链模式        命令模式

                                   备忘录模式          状态模式          访问者模式        中介者模式    


桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与其实现部分分离,使它们可以独立地变化。桥接模式通过引入桥接接口,使得抽象类和实现类可以分别独立扩展,从而解决了多维度变化的问题。这种模式特别适用于那些接口部分和实现部分都需要独立扩展的场景。

模式结构

桥接模式通常包含以下角色:

  1. 抽象类(Abstraction):定义了抽象接口,并维护一个对实现类对象的引用。抽象类不关心具体的实现细节,仅通过接口与实现类交互。

  2. 实现接口(Implementor):定义了实现类需要实现的接口,供抽象类调用。

  3. 具体抽象类(Concrete Abstraction):继承自抽象类,实现了抽象类中与业务相关的操作,并通过构造函数传入实现类对象。具体抽象类可以有多个,每个对应不同的业务场景。

  4. 具体实现类(Concrete Implementor):实现了实现接口,提供了接口的具体实现。具体实现类可以有多个,每个对应不同的实现方式。

工作原理

  • 客户端:通过具体抽象类与系统交互,不需要关心具体的实现细节。
  • 抽象类:定义了抽象接口,并通过持有实现类对象的引用,调用其实现接口的方法。
  • 实现接口:定义了实现类需要实现的通用接口。
  • 具体抽象类:根据具体业务场景,继承抽象类并实现相关业务方法,通过构造函数传入具体的实现类对象。
  • 具体实现类:提供了实现接口的具体实现,供具体抽象类调用。

优缺点

优点
  • 分离抽象与实现:桥接模式将抽象部分与实现部分分离,使得两者可以独立扩展,降低了耦合性。
  • 支持多维度变化:桥接模式可以应对一个类具有两个或多个独立变化维度的情况,每个维度可以通过继承独立扩展。
  • 提高可扩展性:新增抽象类和具体实现类时,不会影响已有的代码,提高了系统的可扩展性。
缺点
  • 增加复杂性:桥接模式引入了额外的抽象层和实现层,增加了系统的复杂性,尤其是对于简单的系统,可能过度设计。
  • 识别抽象和实现的维度困难:识别出系统中独立变化的维度并不总是容易,需要深入理解业务需求和未来可能的变化。

适用场景

  • 系统需要在多个维度上进行变化:当一个系统需要在抽象层次和实现层次上进行独立扩展时,可以使用桥接模式。
  • 接口与实现分离:当接口和实现可以独立扩展,且希望避免多继承带来的问题时,桥接模式是一个很好的选择。
  • 避免类爆炸:当使用继承来处理多维度变化导致类数量急剧增长时,桥接模式可以有效减少类的数量。

代码示例(以Java为例)

// 实现接口
interface DrawingAPI {void drawCircle(double x, double y, double radius);
}// 具体实现类
class DrawingAPI1 implements DrawingAPI {@Overridepublic void drawCircle(double x, double y, double radius) {System.out.println("DrawingAPI1 drawing a circle at (" + x + ", " + y + ") radius " + radius);}
}class DrawingAPI2 implements DrawingAPI {@Overridepublic void drawCircle(double x, double y, double radius) {System.out.println("DrawingAPI2 drawing a circle at (" + x + ", " + y + ") radius " + radius);}
}// 抽象类
abstract class Shape {protected DrawingAPI drawingAPI;protected Shape(DrawingAPI drawingAPI) {this.drawingAPI = drawingAPI;}abstract void draw();
}// 具体抽象类
class CircleShape extends Shape {private double x, y, radius;public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {super(drawingAPI);this.x = x;this.y = y;this.radius = radius;}@Overridevoid draw() {drawingAPI.drawCircle(x, y, radius);}
}// 客户端代码
public class BridgePatternDemo {public static void main(String[] args) {Shape circle1 = new CircleShape(1, 2, 3, new DrawingAPI1());circle1.draw();  // 输出:DrawingAPI1 drawing a circle at (1.0, 2.0) radius 3.0Shape circle2 = new CircleShape(4, 5, 6, new DrawingAPI2());circle2.draw();  // 输出:DrawingAPI2 drawing a circle at (4.0, 5.0) radius 6.0}
}

 在这个Java示例中:

  • DrawingAPI接口定义了绘制圆形的通用接口。
  • DrawingAPI1DrawingAPI2类分别实现了DrawingAPI接口,提供了不同的绘制方式。
  • Shape抽象类定义了抽象接口,并通过构造函数接收一个DrawingAPI对象的引用,实现了与实现类的解耦。
  • CircleShape类继承自Shape,实现了draw()方法,并在构造函数中接收绘制位置和半径参数,以及一个DrawingAPI对象的引用。
  • 客户端代码通过创建CircleShape对象,并传入不同的DrawingAPI实现,实现了基于不同绘制方式绘制圆形,而无需关心具体的绘制细节。

代码示例(以Python为例)

# 实现接口(Implementor)
class RenderingEngine:"""渲染引擎接口"""def render_circle(self, x, y, radius):raise NotImplementedError()def render_rectangle(self, x, y, width, height):raise NotImplementedError()# 具体实现类(Concrete Implementor)
class SketchRenderingEngine(RenderingEngine):"""素描风格渲染引擎"""def render_circle(self, x, y, radius):print(f"Sketch rendering engine is drawing a circle at ({x}, {y}) with radius {radius}.")def render_rectangle(self, x, y, width, height):print(f"Sketch rendering engine is drawing a rectangle at ({x}, {y}) with dimensions ({width}, {height}).")class WatercolorRenderingEngine(RenderingEngine):"""水彩风格渲染引擎"""def render_circle(self, x, y, radius):print(f"Watercolor rendering engine is painting a circle at ({x}, {y}) with radius {radius}.")def render_rectangle(self, x, y, width, height):print(f"Watercolor rendering engine is painting a rectangle at ({x}, {y}) with dimensions ({width}, {height}).")# 抽象类(Abstraction)
class Shape:"""图形抽象类"""def __init__(self, rendering_engine):self.rendering_engine = rendering_enginedef draw(self):raise NotImplementedError()# 具体抽象类(Concrete Abstraction)
class Circle(Shape):"""圆形"""def __init__(self, x, y, radius, rendering_engine):super().__init__(rendering_engine)self.x = xself.y = yself.radius = radiusdef draw(self):self.rendering_engine.render_circle(self.x, self.y, self.radius)class Rectangle(Shape):"""矩形"""def __init__(self, x, y, width, height, rendering_engine):super().__init__(rendering_engine)self.x = xself.y = yself.width = widthself.height = heightdef draw(self):self.rendering_engine.render_rectangle(self.x, self.y, self.width, self.height)# 客户端代码
if __name__ == "__main__":# 创建图形与渲染引擎circle_sketch = Circle(1, 2, 3, SketchRenderingEngine())circle_watercolor = Circle(4, 5, 6, WatercolorRenderingEngine())rect_sketch = Rectangle(7, 8, 9, 10, SketchRenderingEngine())rect_watercolor = Rectangle(11, 12, 13, 14, WatercolorRenderingEngine())# 绘制图形circle_sketch.draw()circle_watercolor.draw()rect_sketch.draw()rect_watercolor.draw()

在这个例子中,我们将模拟一个图形系统,它允许用户绘制不同形状(如圆形、矩形),同时支持多种渲染引擎(如素描风格、水彩风格)。桥接模式在这里帮助我们将图形的抽象定义(形状)与具体的渲染实现(渲染引擎)分离,使得这两部分可以独立扩展。 

在这个Python示例中:

  • RenderingEngine接口定义了绘制圆形和矩形的通用方法。
  • SketchRenderingEngineWatercolorRenderingEngine类分别实现了RenderingEngine接口,提供了不同的绘制风格。
  • Shape抽象类定义了抽象接口,并通过构造函数接收一个RenderingEngine对象的引用,实现了与实现类的解耦。
  • CircleRectangle类继承自Shape,实现了draw()方法,并在构造函数中接收几何属性参数,以及一个RenderingEngine对象的引用。
  • 客户端代码通过创建不同类型的Shape对象,并传入不同的RenderingEngine实现,实现了基于不同渲染风格绘制图形,而无需关心具体的绘制细节。

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

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

相关文章

车企的数智化“内功”,大模型帮修炼

文|白 鸽 编|王一粟 时隔4年回归的北京车展,遇上了中国智能汽车的热潮。 开年价格战的持续洗礼,不仅让一众中国车企都慌得一批,也让全球巨头特斯拉也面临一季度销量大跌局面。 与此同时,智能汽车还在…

C++初识内存管理和模版

目录 前言 1.C/C内存分布 2. C的内存管理方式 2.1 new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new和operator delete函数 4. new和delete的实现原理 4.1 内置类型 4.2 自定义类型 5. malloc/free和new/delete的区别 6. 初识模版 6.1 泛型编…

ERROR: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

今天本来想在A服务器上传文件给B服务器的结果发现明明给root用户设置了密码就是远程登陆不了,后来才发现在容器中很多服务都是没有的,所以刚安装后忘记了修改配置文件,导致远程登陆失败。 报错: 解决方法: 在/etc/ssh…

Leetcode 150:逆波兰表达式求值

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 示例 1: 输入:tokens ["2","1","","3","*"] 输出&…

申请高德地图,报错INVALID_USER_SCODE处理

配置上key后 报错: 解决:将应用类型修改为出行,问题解决 扩展:应用申请 进入应用管理,创建新应用(这里我选了导航,就报了上边的错误) 新应用中添加 key,服务平台选择…

static和extern关键字详解

目录 创作不易,如对您有帮助,还望一键三连,谢谢!!! 回顾 1.作用域和声明周期 1.1作用域 1.2生命周期 2.static和extern 2.1extern 2.2static 2.2-1static修饰局部变量 2.2-2static修饰全局变量 创…

解决在服务器中减少删除大文件夹耗时太久的问题

在数据驱动的现代商业环境中,企业对服务器的高效运作有着极高的依赖性。然而,IT管理员们常常面临一个棘手的问题:删除服务器上的大型文件夹过程缓慢,这不仅降低了工作效率,还可能对用户体验造成负面影响。本文将介绍一…

2024 年 Rust 开发者路线图

Rust 近年来因其对性能、安全性和并发性的关注而广受欢迎。作为一名开发人员,掌握 Rust 可以为各种机会打开大门,包括 Web 开发。 在 github 上发现了这个优秀的路线图,由 Anshul Goyal 创建,它提供了一条全面的路径,概…

MIEC CS172(Prolog)

Chapter 1 and 2 Fact Facts: Facts are statements that areassumed to be true. The dot ‘.’ character must come at the end of a fact. Example: We want to tell “John likes Mary” : English interpretation The standard form of fact in Prolog Likes (john, ma…

怎么用AI绘画进行人物修复?

用过AI绘画生成人物图片的朋友们是不是都碰到过这样的问题:诡异的造型、崩坏的五官、离谱的手指头、乱七八糟的背景...指望AI一次性生成百分百完美的图貌似有点难啊。 现在AI绘画有了【脸部修复】【手部修复】功能,就能够轻松解决这些的问题了&#xff0…

Facebook的时间机器:回溯社交媒体的历史

1. 社交媒体的起源与早期模式 社交媒体的历史可以追溯到互联网的早期发展阶段。在Web 1.0时代,互联网主要是一个信息发布平台,用户主要是被动地接收信息。但随着Web 2.0的兴起,互联网逐渐转变为一个互动和参与的平台,社交媒体应运…

2024.4.23 关于 LoadRunner 性能测试工具详解 —— VUG

目录 引言 LoadRunner 三大组件之间的关系 LoadRunner 脚本录制 启动并访问 WebTours 脚本录制 编译 运行(回放) LoadRunner 脚本加强 事务插入 插入集合点 插入检查点 参数化 ​编辑 打印日志 引言 问题: 此处为啥选择使用 Lo…

JdbcTemplate详解

1 概述 为了使JDBC更加易于使用,Spring在JDBC API上定义了一个抽象层,以此建立一个JDBC存取框架。 作为Spring JDBC框架的核心,JDBC模板的设计目的是为不同类型的JDBC操作提供模板方法,通过这种方式,可以在尽可能保留…

Linux安装Docker的多版本PHP和多版本MySQL共存

1: 先安装docker 安装完后执行,权限设置 sudo usermod -aG docker $USER或者sudo usermod -aG docker kentrl#添加当前用户到Docker用户组中 sudo newgrp docker#更新用户组数据,必须执行否则无效 sudo systemctl restart docker 先看目录结构: 2:按照目录结构挂载磁盘,…

探究C++20协程(6)——实现协程之间消息传递

之前主要关注的是协程与外部调用者的交互,这次也关注一下对等的协程之间的通信。 实现目标 在C中实现协程的Channel相对复杂,因为C标准库中并没有内置的协程间通信机制。C20引入了协程支持,但主要提供了底层的协程操作,如协程的…

反序列bit

#include <stdio.h> #include <stdint.h> #include <stdbool.h> // 定义描述反序列化信息的结构体 typedef struct { const uint32_t *data; // 数据数组 int num_elements; // 数据数组的元素数量 int bit_position; // 当前位偏移量&#xff08;以位为单位…

程序员学习编程新方式:【YDUIbuilder】,让技术触手可及!

想象一下&#xff0c;构建#软件# 就像搭积木一样简单有趣&#xff01;[#YDUIbuilder]#开源项目# 低代码平台&#xff0c;将这一梦想变为现实。这里&#xff0c;创新不再是#程序猿# 的专利&#xff0c;而是每个人的超能力&#xff01; 来[YDUIbuilder]&#xff0c;你将体验到&am…

System1和System2

System 1 和 System 2 是心理学家丹尼尔卡尼曼(Daniel Kahneman)在其著作《快思慢想》(Thinking, Fast and Slow)中描述的两种思维模式。这两个系统代表我们大脑处理信息和做决策的不同方式。 System 1(系统1) 这是我们的“快速思考”系统。它是无意识的、直觉的、自动…

【Qt常用控件】—— QWidget 核心属性

目录 &#xff08;一&#xff09;控件概述 1.1 关于控件体系的发展 &#xff08;二&#xff09;QWidget 核心属性 2.1 核心属性概览 2.2 enabled 2.3 geometry 2.4 windowTitle 2.5 windowIcon 2.6 windowOpacity 2.7 cursor 2.8 font 2.9 toolTip 2.10 focus…

Esko Ukkonen: On-line Construction of Suffix Trees

Esko Ukkonen: On-line Construction of Suffix Trees 文章目录 Esko Ukkonen: On-line Construction of Suffix Trees一、后缀树的概念及应用【详见刘方州同学报告】1.1 字典树 Trie1.2 后缀树 Suffix Tree2 后缀树的应用 二、朴素后缀树构造方法及问题三、线性时间内后缀树在…