【设计模式】适配器和桥接器模式有什么区别?

今天我探讨一下适配器模式和桥接模式,这两种模式往往容易被混淆,我们希望通过比较他们的区别和联系,能够让大家有更清晰的认识。

适配器模式:连接不兼容接口

当你有一个类的接口不兼容你的系统,而你又不希望修改这个类的源代码时,适配器模式就能派上用场。适配器模式作用在已有组件的接口层面,使之能够满足客户端的期望接口

img

例如,你有一台彩色打印机,但是你的图形处理系统只支持黑白打印机:

// 你的图形处理系统只能接受这个接口
interface BlackWhitePrinter {void printBlackWhite();
}// 但是你有的是彩色打印机:
class ColorPrinter {void printColor() {System.out.println("Printing Color");}
}// 适配器模式就派上用场了
class PrinterAdapter implements BlackWhitePrinter {private final ColorPrinter colorPrinter;public PrinterAdapter(ColorPrinter colorPrinter) {this.colorPrinter = colorPrinter;}@Overridepublic void printBlackWhite() {colorPrinter.printColor();}
}
桥接模式:划分接口和实现

桥接模式通过将抽象和实现解耦,使得两者可以独立进行变化。它的主要目标是避免当修改实现时,需要同时修改接口

img

比如我们有一个图形API,定义有多种形状,比如矩形、圆形等。同时,每种形状都可能有多种绘制方式,比如OpenGL、Vulkan。如果不采用桥接模式,很可能会出现类名如OpenGLRectangle, OpenGLCircle, VulkanRectangle, VulkanCircle…这显然是一种不好的设计,因为每次添加或修改一个图形类型或绘制方式,都会影响另一方。

而相反,通过桥接模式,我们可以把Shape和DrawAPI解耦:

interface DrawAPI {    // 抽象接口void draw();
}
class Shape {protected DrawAPI api;   public Shape(DrawAPI api)  {this.api = api;}public void draw() {api.draw();  // 调用实现}          
}class OpenGL implements DrawAPI {@Overridepublic void draw() {System.out.println("OpenGL drawing");}
}
class Vulkan implements DrawAPI {@Overridepublic void draw() {System.out.println("Vulkan drawing");}
}

这样我们就可以任意组合Shape和DrawAPI:

Shape openglShape = new Shape(new OpenGL());
Shape vulkanShape = new Shape(new Vulkan());
两者的区别和联系

虽然适配器模式和桥接模式在表面上有诸多相似之处,比如他们都试图使得两个或以上的类或接口能够协同工作,但是他们的应用场景和目标是不一样的。

适配器模式关注的是如何使已有组件能够适应你的接口以达到代码重用,它解决的是“已经存在”的问题。

而桥接模式关注的是如何设计你的抽象和实现,使其能够独立变化,它解决的是“尚未发生”的问题。

更进一步的讲:

  1. 适配器模式适配器模式的主要目标是让原本接口不兼容的两个接口可以协同工作。它通常被用在已经存在的系统中,以解决现有组件与系统其他部分的兼容性问题。通常情况下,适配器会封装已经存在的组件,并提供一个与系统其余部分兼容的接口。
  2. 桥接模式桥接模式的主要目标在于将抽象与实现解耦,使得两者可以独立地变化。这种解耦使得抽象和实例化可以沿着各自的轴线变化,也就是说,抽象层次结构的改变不会影响到实例化层次结构的改变,反之亦然。

希望这篇文章能够帮助你理解适配器模式和桥接模式,以及他们的区别和联系。学习设计模式是一个长期的过程,不要着急,慢慢积累,总会有收获的。

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

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

相关文章

mini-spring-Bean含参实例化(三)

上一节,bean是在AbstractAutowireCapableBeanFactory.doCreateBean方法中用beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的情况。 本节考虑含参的bean的实例化 考虑两个问题 一、串流程从哪合理的把构造函数的入参信息传递到实例化操作里…

各行业领域向chatgpt高质量提问的方式

一、技术/业务/事项咨询: ChatGPT可以回答关于技术领域以及工作生活等各方面的问题,包括最佳实践、开发工具、编程语言选择等,咨询标准方案等。 常见问法: 我准备做***,【目前的选择有***】,请告诉我选哪…

sql注入基础

一、SQL注入攻击的根源可以归结为两个主要因素: 程序命令和用户数据之间缺乏有效的隔离措施,以及对用户输入数据的信任。 程序命令和用户数据之间缺乏隔离:在一个应用程序中,程序命令(如SQL语句)和用户数据(即用户输入)应该被严格分离,以避免恶意用户利用输入数据来改…

云服务器定价_云服务器价格_云主机计费模式_腾讯云

腾讯云服务器租用价格表:轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三年、2核4G5M带宽218元一年,2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月,云服务器CVM S5实例2核2G配置280.8元一年…

嵌入式培训机构四个月实训课程笔记(完整版)-C++和QT编程第六天-Qt UDP编程(物联技术666)

链接:https://pan.baidu.com/s/1-u7GvgM0TLuiy9z7LYQ80Q?pwd1688 提取码:1688 在Qt中提供了QUdpSocket 类来进行UDP数据报(datagrams)的发送和接收。这里我们还要了解一个名词Socket,也就是常说的“套接字”。 Qt 网络…

2024.1.18力扣每日一题——拿出最少数目的魔法豆

2024.1.18 题目来源我的题解方法一 排序前缀和方法二 优化版本 题目来源 力扣每日一题;题序:2171 我的题解 方法一 排序前缀和 结果与原始顺序无关,因此先进行排序,然后计算前缀和。 有官方题解证明:最终在 拿出最少…

ImageMagick使用手册

ImageMagick使用手册 文章目录 ImageMagick使用手册ImageMagick是什么指令总结1.查看版本2.官网验证指令解读3.svg转png4.png转ico5.将指定文件夹中的所有PNG图像转换为ICO图标 本教程持续更新,我学到多少就更新多少。关于ffmpeg如何安装可以看上一篇博客win系统环境…

zk集群--启动阶段集群选举

1.概述 zk作为一个内存数据库产品,启动一个zk实例对外提供服务的方式成为单机模式。既然单机模式就可以实现请求处理,那为何要引入集群模式呢,引入集群模式付出了那些代价呢,相应的有取得了那些收益呢? 首先&#xf…

强化学习(四)动态规划——1

动态规划算法(DP):在马尔可夫决策过程(MDP)的完美环境模型下计算最优策略。但其在强化学习中实用性有限,其一是它是基于环境模型已知;其二是它的计算成本很大。但它在理论伤仍然很重要&#xff…

【Unity】RayMarching体积云理论学习

RayMarching 体积云 RayMarching 是一种处理体积物体的方法 RayMarching 体积云的制作是基于屏幕后处理 屏幕空间重建世界坐标 目的是把屏幕坐标的每一个像素点转化成Unity世界坐标,可以得到射线的方向 如何在需要渲染的物体或者场景中使用RayMarching&#xff…

2023年12月青少年机器人技术等级考试(五级)理论综合试卷

2023年12月青少年机器人技术等级考试(五级)理论综合试卷 单选题 第 1 题 单选题 通常状况下,ESP32 WROOM模组的工作电压是?( ) A.3V B.3.3V C.3.6V D.5V 第 2 题 单选题 ESP32 WROOM模组中核&am…

PHP AES加解密示例【详解】

PHP AES加解密示例 前言 在Web开发中,数据的安全性至关重要。AES(Advanced Encryption Standard)是一种常用的对称加密算法,用于保护敏感数据的安全性。本文将详细介绍在PHP中如何使用AES算法进行加解密操作,以确保数…

java大数据hadoop2.9.2 Linux安装mariadb和hive

一、安装mariadb 版本centos7 1、检查Linux服务器是否已安装mariadb yum list installed mariadb* 2、如果安装了,想要卸载 yum remove mariadb rm -rf /etc/my.cnf rm -rf /var/lib/mysql 才能完全删除 3、安装mariadb 在线网络安装 yum install -y mari…

Webpack5入门到原理17:Loader 原理

loader 概念 帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块。 loader 执行顺序 分类 pre: 前置 loadernormal: 普通 loaderinline: 内联 loaderpost: 后置 loader 执行顺序 4 类 loader 的执行优级为&#xff…

【ARM 嵌入式 编译系列 2.6 -- GCC 编译时间统计参数 -ftime-report -Q 】

请阅读【嵌入式开发学习必备专栏 之 ARM GCC 编译专栏】 文章目录 GCC 编译时间统计 GCC 编译时间统计 如果你想要统计 GCC 编译过程中各个阶段的时间,可以使用 GCC 的 -ftime-report 选项。这个选项可以让编译器在编译结束后报告每个编译阶段所花费的时间。要使用…

Linux fsck命令教程:如何检查和修复你的文件系统(附实例详解和注意事项)

Linux fsck命令介绍 fsck,全称File System Consistency Check,主要用于检查和修复Linux文件系统的不一致和错误。该工具用于解决潜在的文件系统问题。fsck可以为你提供检查和修复一切文件系统中的问题的功能,包括一些潜在的磁盘错误等。 Li…

网络通信(Socket/TCP/UDP)

一、Socket 1.概念: Socket(又叫套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接协议,客户端的IP地址,客户端的端口,服务器的IP地址,服务器的端口。 一个Socket是一对IP地址…

笔试面试题——二叉树进阶(一)

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、根据二叉树创建字符串1、题目讲解2、思路讲解3、代码实现 二、二叉树的分层遍历1、题目讲…

【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数

1.gets函数与puts函数 gets函数类似于scanf函数,用于读取标准输入.前面我们已经知道scanf函数在读取字符串时遇到空格就认为读取结束,所以当输入的字符串存在空格时,我们需要使用gets 函数进行读取. gets函数的格式如下: char *…

大数据导论(4)---大数据应用

文章目录 1. 在互联网中的应用1.1 推荐系统1.2 长尾理论1.3 推荐方法与模型1.4 推荐系统应用 2. 在其他领域的应用2.1 企业营销2.2 智慧交通 1. 在互联网中的应用 1.1 推荐系统 1. 推荐系统产生:  (1) 互联网的飞速发展使我们进入了信息过载的时代,搜索…