【深入理解设计模式】桥接设计模式

在这里插入图片描述

桥接设计模式

桥接设计模式是一种结构型设计模式,它旨在将抽象部分与实现部分分离,使它们可以独立变化,从而更好地管理复杂性。桥接模式通常涉及多个层次的抽象,其中一个层次(通常称为"抽象")依赖于另一个层次(通常称为"实现")的实例。

定义:

​ 将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

结构:

  • 抽象化(Abstraction)角色 :定义抽象类,并包含一个对实现化对象的引用。
  • 扩展抽象化(Refined Abstraction)角色 :是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化(Implementor)角色 :定义实现化角色的接口,供扩展抽象化角色调用,它可以是一个接口或一个抽象类。实现并不一定要与抽象完全匹配,但必须提供抽象所需的方法。
  • 具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。

案例一:

// 实现部分接口
interface DrawingAPI {void drawCircle(double x, double y, double radius);
}// 具体实现部分A
class DrawingAPI1 implements DrawingAPI {@Overridepublic void drawCircle(double x, double y, double radius) {System.out.printf("API1.drawCircle at %f:%f radius %f%n", x, y, radius);}
}// 具体实现部分B
class DrawingAPI2 implements DrawingAPI {@Overridepublic void drawCircle(double x, double y, double radius) {System.out.printf("API2.drawCircle at %f:%f radius %f%n", x, y, radius);}
}// 抽象部分
abstract class Shape {protected DrawingAPI drawingAPI;protected Shape(DrawingAPI drawingAPI) {this.drawingAPI = drawingAPI;}public abstract void draw();
}// 扩充抽象部分
class Circle extends Shape {private double x, y, radius;public Circle(double x, double y, double radius, DrawingAPI drawingAPI) {super(drawingAPI);this.x = x;this.y = y;this.radius = radius;}@Overridepublic void draw() {drawingAPI.drawCircle(x, y, radius);}
}public class BridgePatternExample {public static void main(String[] args) {// 使用实现部分A来画一个圆Shape circle = new Circle(1, 2, 3, new DrawingAPI1());circle.draw();// 使用实现部分B来画一个圆Shape anotherCircle = new Circle(5, 7, 11, new DrawingAPI2());anotherCircle.draw();}
}

在上面的示例中,DrawingAPI 接口代表了实现部分,DrawingAPI1DrawingAPI2 分别是具体的实现部分。Shape 是抽象部分,Circle 是扩充抽象部分。在 Circle 类中,通过 drawingAPI 调用实现部分的方法来绘制圆。在 BridgePatternExample 类的 main 方法中,我们可以看到如何使用不同的实现部分来绘制不同的圆。

案例二:

【例】视频播放器

需要开发一个跨平台视频播放器,可以在不同操作系统平台(如Windows、Mac、Linux等)上播放多种格式的视频文件,常见的视频格式包括RMVB、AVI、WMV等。该播放器包含了两个维度,适合使用桥接模式。

类图如下:

/*** @author OldGj 2024/02/26* @version v1.0* @apiNote 视频文件 - 抽象实现化角色*/
public interface VideoFile {public void decode(String fileName);}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote RMVB类型的视频文件  - 具体实现化角色*/
public class RMVBFile implements VideoFile {@Overridepublic void decode(String fileName) {System.out.println("rmvb: " + fileName);}
}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote Avi格式的视频文件 - 具体实现化角色*/
public class AVIFile implements VideoFile{@Overridepublic void decode(String fileName) {System.out.println("avi : "+fileName);}
}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote 操作系统类 - 抽象化角色*/
public abstract class OperatingSystemVersion {//维护一个对实现的引用protected VideoFile videoFile;public OperatingSystemVersion(VideoFile videoFile) {this.videoFile = videoFile;}public abstract void play(String fileName);
}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote MAC操作系统 - 扩展抽象化角色*/
public class Mac extends OperatingSystemVersion{public Mac(VideoFile videoFile) {super(videoFile);}@Overridepublic void play(String fileName) {System.out.println("mac");videoFile.decode(fileName);}
}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote window操作系统 - 扩展抽象化角色*/
public class Window extends OperatingSystemVersion{public Window(VideoFile videoFile) {super(videoFile);}@Overridepublic void play(String fileName) {System.out.println("window");videoFile.decode(fileName);}
}
/*** @author OldGj 2024/02/26* @version v1.0* @apiNote 客户端 - 测试类*/
public class Client {public static void main(String[] args) {OperatingSystemVersion systemVersion = new Window(new RMVBFile());systemVersion.play("战狼");}
}

在这里插入图片描述

桥接模式是如何进行分离抽象和实现的?

假设我们要设计一个画图应用程序,它可以在不同的平台上绘制不同的形状,比如在 Windows 平台上绘制矩形和圆形,在 Linux 平台上绘制矩形和椭圆形。

首先,我们定义两个抽象类:ShapeDrawingAPI

// 抽象类 Shape
abstract class Shape {protected DrawingAPI drawingAPI;protected Shape(DrawingAPI drawingAPI) {this.drawingAPI = drawingAPI;}public abstract void draw(); // 抽象方法,绘制形状
}// 抽象类 DrawingAPI
interface DrawingAPI {void drawShape(); // 抽象方法,绘制形状
}

然后,我们定义具体的形状类,比如矩形和圆形,并且实现了 Shape 抽象类。

// 具体形状类 Rectangle
class Rectangle extends Shape {public Rectangle(DrawingAPI drawingAPI) {super(drawingAPI);}@Overridepublic void draw() {drawingAPI.drawShape(); // 调用实现部分的绘制方法}
}// 具体形状类 Circle
class Circle extends Shape {public Circle(DrawingAPI drawingAPI) {super(drawingAPI);}@Overridepublic void draw() {drawingAPI.drawShape(); // 调用实现部分的绘制方法}
}

接下来,我们实现两个不同的绘制API,比如在 Windows 平台和 Linux 平台上的绘制。

// 具体实现部分 DrawingAPI for Windows
class DrawingAPIWindows implements DrawingAPI {@Overridepublic void drawShape() {System.out.println("Drawing shape on Windows platform");}
}// 具体实现部分 DrawingAPI for Linux
class DrawingAPILinux implements DrawingAPI {@Overridepublic void drawShape() {System.out.println("Drawing shape on Linux platform");}
}

最后,我们在客户端代码中使用桥接模式来创建对象并调用方法。

public class BridgePatternExample {public static void main(String[] args) {// 在 Windows 平台上绘制矩形Shape rectangleWindows = new Rectangle(new DrawingAPIWindows());rectangleWindows.draw();// 在 Linux 平台上绘制圆形Shape circleLinux = new Circle(new DrawingAPILinux());circleLinux.draw();}
}

在这个例子中,抽象部分是 Shape 抽象类,具体形状类 RectangleCircle 是扩充抽象部分。实现部分是 DrawingAPI 接口,具体实现部分 DrawingAPIWindowsDrawingAPILinux 分别是不同平台上的具体实现。

通过使用桥接模式,我们成功地将抽象部分和实现部分分离开来,使它们可以独立变化。例如,如果要在 Windows 平台上绘制其他形状,只需创建一个新的具体形状类,并提供相应的 DrawingAPIWindows 实现即可,而不需要修改现有的代码。这种设计使得系统更加灵活、可扩展和易于维护。

桥接模式的优点包括:

  • 分离抽象和实现,使得它们可以独立变化,降低了系统的耦合度。
  • 提高了系统的可扩展性,可以方便地增加新的抽象和实现。
  • 提高了系统的可维护性,通过分离抽象和实现,减少了修改一个层次对另一个层次的影响。

使用场景

  • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时
  • 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
  • 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。

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

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

相关文章

防御保护----内容安全

八.内容安全--------------------------。 IAE引擎: IAE引擎里面的技术:DFI和DPI技术--- 深度检测技术 DPI --- 深度包检测技术--- 主要针对完整的数据包(数据包分片,分段需要重组),之后对 数据包的内容进行…

【leetcode热题】三角形最小路径和

难度: 中等通过率: 37.6%题目链接:. - 力扣(LeetCode) 题目描述 给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。 例如,给定三角形: [[2],[3…

goland配置新增文件头

参考: goland函数注释生成插件 goland函数注释生成插件_goland自动加函数说明-CSDN博客 GoLand 快速添加方法注释 GoLand 快速添加方法注释_goland批量注释-CSDN博客 goland 如何设置头注释,自定义author和data goland 如何设置头注释,自定…

Web JavaScript

目录 1 前言2 原生js常见用法2.1 弹窗操作2.2 for循环操作2.3 打印日志操作2.4 获取页面值操作2.5 判空操作2.6 修改页面内容操作2.7 网页版计算器制作 3 外部js常见用法4 总结 1 前言 JavaScript 是一种脚本,一门编程语言,它可以在网页上实现复杂的功能…

如何理解Rust中的对象

先看看下面2段代码,第1段代码正常,第2段却编译失败,为什么呢? fn main() {let a: u32 5;let b a;println!("a{a}, b{b}"); }正常 fn main() {let a String::from("Hello");let b a;println!("a{a}…

python中如何引用正则表达式?

无极低码 :https://wheart.cn 引言 正则表达式(Regular expressions,也叫 REs、 regexs 或 regex patterns),本质上是嵌入 Python 内部并通过 re 模块提供的一种微小的、高度专业化的编程语言。使用这种小语言&#…

事件循环解析

浏览器的进程模型 何为进程? 程序运行需要有它自己专属的内存空间,可以把这块内存空间简单的理解为进程 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 何为线程? 有了进程后&…

8.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-游戏底层功能对接类GameProc的实现

内容参考于:易道云信息技术研究院VIP课 上一个内容:通过逆向分析确定游戏明文接收数据过程 码云地址(master 分支):https://gitee.com/dye_your_fingers/titan 码云版本号:bcf7559184863febdcad819e48aa…

python number类型中的各种数学函数

python中的数学函数 函数返回值 ( 描述 )abs(x)返回数字的绝对值&#xff0c;如abs(-10) 返回 10ceil(x)返回数字的上入整数&#xff0c;如math.ceil(4.1) 返回 5cmp(x, y)如果 x < y 返回 -1, 如果 x y 返回 0, 如果 x > y 返回 1。Python 3 已废弃&#xff0c;使用 (…

QT信号槽实现分析

1.宏定义 qt中引入了MOC来反射&#xff0c;编译阶段变成 MOC–>预处理–>编译–>汇编–>链接 1-1、Q_OBJECT 这个宏定义了一系列代码&#xff0c;包括元对象和处理的函数 #define Q_OBJECT \public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static c…

如何学习Arduino单片机

&#xff08;本文为简单介绍&#xff0c;内容源于网络&#xff09; 学习Arduino相关的网址和开源社区&#xff1a; Arduino官方文档: Arduino - HomeArduino Forum: Arduino ForumArduino Playground: Arduino Playground - HomePageGitHub: GitHub: Let’s build from here …

AE电源Apex Generator 系列5708009-C 使用说明 文件内容可以看目录,包含使用,调试,安装等内容都有160页

AE电源Apex Generator 系列5708009-C 使用说明 文件内容可以看目录&#xff0c;包含使用&#xff0c;调试&#xff0c;安装等内容都有160页

2.26 Qt day4+5 纯净窗口移动+绘画事件+Qt实现TCP连接服务+Qt实现连接数据库

思维导图 Qt实现TCP连接 服务器端&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTcpServer>//服务器端类 #include<QTcpSocket>//客户端类 #include<QMessageBox>//消息对话框类 #include<QList>//链…

exec函数族 和 线程 学习

一.exec函数族 extern char **environ; int execl(const char *path, const char *arg, ... &#xff08;后面跟的参数&#xff09; /* (char *) NULL */); eg&#xff1a; int main(void) //execl用法 {printf("");exec…

nginx管理命令

nginx管理命令 ngnix作用是多个进程处理网络请求。一部分是管理命令&#xff0c;一部分是配置文件。 nginx管理命令 两种管理方式nginx管理和systemctl管理&#xff0c;注意使用哪种方式开始就用哪种方式结束。 1. nginx管理方式 nginx -t : 检测nginx.conf配置文件的语法 …

【项目管理需求分析】环境决定了你能看到什么

文章目录 前言基层的痛1.业务提不出需求2.建议不可取 总结 前言 近期工作中有所感悟&#xff0c;乘着春节的尾巴不是很忙&#xff0c;就记录下来。 随着公司的不断扩大&#xff0c;总公司、省公司、市公司、县公司&#xff5e;&#xff0c;纵向越来越深&#xff0c;科技专业人…

react脚手架

1.react概述 1.1 什么是react React是一个用于构建用户界面的JS库。 用户界面&#xff1a;HTML页面&#xff08;前端&#xff09; React主要用来写HTML界面&#xff0c;或构建Web应用 如果从MVC的角度来看&#xff0c;React仅仅是视图层&#xff08;V&#xff09;,也就是只负…

亿道丨三防平板丨手持平板丨加固平板丨助力地震救援

自土耳其发生7.8级大地震以来&#xff0c;一直都牵动着世人的心。2023年2月10日&#xff0c;据法新社最新消息&#xff0c;强震已造成土耳其和叙利亚两国超2万人遇难。报道称&#xff0c;相关官员和医护人员表示&#xff0c;地震造成土耳其17674人死亡&#xff0c;叙利亚则有33…

Nginx+Tomcat实现动静分离

文章目录 一.动静分离的原理及架构1.1 动静分离是什么&#xff1f;1.2 动静分离的原理1.3 动静分离的架构组成 二.NginxTomcat实现动静分离2.1实验环境2.2所需软件环境2.3nginx服务的实现2.4配置动静分离 一.动静分离的原理及架构 1.1 动静分离是什么&#xff1f; 动静分离(S…