【设计模式】适配器和桥接器模式有什么区别?
今天我探讨一下适配器模式和桥接模式,这两种模式往往容易被混淆,我们希望通过比较他们的区别和联系,能够让大家有更清晰的认识。
适配器模式:连接不兼容接口
当你有一个类的接口不兼容你的系统,而你又不希望修改这个类的源代码时,适配器模式就能派上用场。适配器模式作用在已有组件的接口层面,使之能够满足客户端的期望接口。

例如,你有一台彩色打印机,但是你的图形处理系统只支持黑白打印机:
// 你的图形处理系统只能接受这个接口
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();}
}
桥接模式:划分接口和实现
桥接模式通过将抽象和实现解耦,使得两者可以独立进行变化。它的主要目标是避免当修改实现时,需要同时修改接口。

比如我们有一个图形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());
两者的区别和联系
虽然适配器模式和桥接模式在表面上有诸多相似之处,比如他们都试图使得两个或以上的类或接口能够协同工作,但是他们的应用场景和目标是不一样的。
适配器模式关注的是如何使已有组件能够适应你的接口以达到代码重用,它解决的是“已经存在”的问题。
而桥接模式关注的是如何设计你的抽象和实现,使其能够独立变化,它解决的是“尚未发生”的问题。
更进一步的讲:
- 适配器模式:适配器模式的主要目标是让原本接口不兼容的两个接口可以协同工作。它通常被用在已经存在的系统中,以解决现有组件与系统其他部分的兼容性问题。通常情况下,适配器会封装已经存在的组件,并提供一个与系统其余部分兼容的接口。
- 桥接模式:桥接模式的主要目标在于将抽象与实现解耦,使得两者可以独立地变化。这种解耦使得抽象和实例化可以沿着各自的轴线变化,也就是说,抽象层次结构的改变不会影响到实例化层次结构的改变,反之亦然。
希望这篇文章能够帮助你理解适配器模式和桥接模式,以及他们的区别和联系。学习设计模式是一个长期的过程,不要着急,慢慢积累,总会有收获的。
相关文章:
【设计模式】适配器和桥接器模式有什么区别?
今天我探讨一下适配器模式和桥接模式,这两种模式往往容易被混淆,我们希望通过比较他们的区别和联系,能够让大家有更清晰的认识。 适配器模式:连接不兼容接口 当你有一个类的接口不兼容你的系统,而你又不希望修改这个…...
C语言应用层程序热补丁
一、热补丁简介 一个正在运行的程序,要是有某函数或某流程有问题,需要修改,有两个方式: 1.通过设置LD_PRELOAD把需要的库重新定向,但这种方式需要重启正在运行的程序。 2.通过修改可执行文件某个函数指向的地址&…...
【代码随想录+力扣hot100】双指针
文章目录 27. 移除元素思路:代码: 26. 删除有序数组中的重复项代码:思路一:重复元素必相邻思路二:从第一个位置开始考虑快慢指针 977.有序数组的平方思路:代码: 283. 移动零代码:思路…...
【Java程序员面试专栏 专业技能篇】MySQL核心面试指引(三):性能优化策略
关于MySQL部分的核心知识进行一网打尽,包括三部分:基础知识考察、核心机制策略、性能优化策略,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第三部分:性能优化策略,子节点表示追问或同级提问 读写分离 分布式数据库的…...
qnx 上screen + egl + opengles 最简实例
文章目录 前言一、qnx 上的窗口系统——screen二、screen + egl + opengles 最简实例1.使用 addvariant 命令创建工程目录2. 添加源码文件3. common.mk 文件4. 编译与执行总结参考资料前言 本文主要介绍如何在QNX 系统上使用egl和opengles 控制GPU渲染一个三角形并显示到屏幕上…...
python基础学习-02
基本的程序设计模式 任何的程序设计都包含IPO,它们分别代表如下: I:Input 输入,程序的输入 P:Process 处理,程序的主要逻辑过程 O:Output 输出,程序的输出 因此如果想要通过计算…...
服务调用Ribbon,LoadBalance,Feign
服务调用Ribbon、Fegin Ribbon实现负载均衡的原理 1:LoadBalancerAutoConfiguration这个类,这个类主要做的就是把LoadBalancer拦截器封装到RestTemplte拦截器集合里面去。 2:然后在代码里面调用restTemplate.getForObject或者其他方法的时候&…...
一条sql是如何运行的
在我们平时使用sql的时候,基本是基于黑盒的使用方式,在客户端输入一条sql语句,然后回显想要的数据,对于mysql server端内部如何运行的以及与存储引擎如何交互的不得而知。 通过下面一幅图,大致描述客户端和服务端交互…...
SystemC学习笔记(三) - 查看模块的波形
简述 波形在Simulation/Emulation中地位十分重要,尤其是在研发初期,只能通过波形来查看软件hang住的位置。 对于TLM来说,查看波形一般是指查看pvbus上的transaction,而对于SystemC本身来说,查看波形就是使用Gtkwave或…...
计算机网络(第六版)复习提纲5
SS2.2 有关信道的几个基本概念 2.通信模型 三个主要部分:信源、信道、信宿 3.通信方式: a)术语:消息(传递的内容)、数据(传递的形式)、信号(数据表现形式,有模拟信号和数字信号两种&…...
JavaScript 学习笔记(WEB APIs Day3)
「写在前面」 本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容: 1. JavaScript 学习笔记(Day1) 2. JavaSc…...
Springboot自动装配:三个注解、Selector、spring.factories文件、@ConditionalOnProperty注解
借鉴: 这个链接是包含run方法进来debug看整个过程的,建议先看:https://www.cnblogs.com/starsray/p/15580915.html https://blog.csdn.net/fengxiandada/article/details/130080828 Springboot自动装配 1.创建springboot应用 如何创建一个s…...
软件工程应用题汇总
绘制数据流图(L0/L1/L2) DFD/L0(基本系统模型) 只包含源点终点和一个处理(XXX系统) DFD/L1(功能级数据流图)在L0基础上进一步划分处理(XXX系统) 个人理解 DFD/L2(在L1基础上进一步分解后的数据流图) 数据…...
P1789 【Mc生存】插火把(C语言)
首先,我们可以先用数组来储存地图(建议用int,我试过bool会RE) 每次读入火把和萤石的坐标 接着把能照亮的地方标记起来 最后用计数器统计会生成怪的地方有钻石的话还怕怪吗 最后,上代码 #include<stdio.h> i…...
计算机网络(第六版)复习提纲6
SS2.3 导引型传输媒体 1.三类位非导引型传输媒体 a)双绞线:两根铜线平行会相互干扰,垂直干扰最小,双绞线近似垂直,绞合度越高,可用的数据传输率越高。 i.无屏蔽双绞线UTP(便宜) ii.屏蔽双绞线&a…...
安卓平板局域网内远程控制工控机方法
安卓平板局域网内远程控制工控机方法 将所需要远程控制的工控机通过网线连接到具有WiFi功能的路由器上,将安卓平板连接上WiFi,如下图所示 下载NoMachine远程软件安装包,官网地址:https://www.nomachine.com/ 点击Download now按钮…...
pinctrl子系统简介
一. 简介 上一章我们编写了基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。 Linux 是一个庞大而完善的系统, 尤其是驱动框架,像 GPIO …...
基于51单片机的温度报警控制系统Protues仿真设计
目录 一、设计背景 二、实现功能 三、总体硬件设计 四、仿真演示 四、源程序 一、设计背景 随着现代工农业技术的发展及人们对生活环境要求的提高,人们也迫切需要检测与了解环境温度。特别地,高温情况下极易造成火灾,例如,在…...
多级缓存
一、多级缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: •请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 •Redis缓存失效时ÿ…...
【已解决】如何用typedef简化函数指针
博文内容简短,主要介绍typedef简化函数指针,形式是typedef int(*pp)(int,int);并用一个加法的例子去演示,如何用typedef简化函数指针。 示例 #include<stdio.h> int add(int a,int b) {return a b; } typedef int(*p)(int, int); in…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
