当前位置: 首页 > news >正文

【设计模式】适配器模式和桥接模式

适配器模式

适配器模式 : 就是将一个类的接口变成客户端所期望的另一种接口,使得原本因为接口不匹配而无法一起工作的接口可以正常工作。属于结构型模式

比方说我有一个A牌子的奶瓶,然后买了个B牌子的奶嘴,不能匹配怎么办? 再买一个转换器就好了

在软件开发中,基本上任何问题都可以通过加一个中间层(抽象)来解决

适配器模式一般包含三种角色 :

目标角色Target : 也就是客户端期望的接口
源角色Adaptee: 已有的接口,内容满足要求,但是客户端无法接入
适配器 Adapter:

适配器可分为三类 :类适配器,对象适配器,接口适配器 (其核心思想都是让Adapter同时具有Target和Adaptee的特性)

以生活中的的电压为例,我们需要将民用的220V的交流电转换为手机可以接收的5V的直流电

public interface IDV5VTarget {int output5V();
}
public class AC220VAdaptee {public int output220V() {int output = 220;System.out.println("输出电压:" + output + "V");return output;}
}

类适配器: 基于继承实现,Adapter继承Adaptee

public class ClassAdapter extends AC220VAdaptee implements IDV5VTarget{@Overridepublic int output5V() {int output = super.output220V()/44;System.out.println("转换后的电压为" + output + "V");return output;}
}

对象适配器 : 基于组合实现,Adapter持有Adaptee对象

public class ObjectAdpater implements IDV5VTarget{private AC220VAdaptee ac220VAdaptee;public ObjectAdpater(AC220VAdaptee ac220VAdaptee) {this.ac220VAdaptee = ac220VAdaptee;}@Overridepublic int output5V() {int output =  this.ac220VAdaptee.output220V()/44;System.out.println("转换后的电压为:" + output + "V");return output;}
}

接口适配器 : 如果接口定义的方法过多,通过接口适配器可以让我们只实现需要转换的方法(直接实现接口的话就会有很多空实现的方法)

总结

优点 :

  1. 通过适配器模式,客户端可以使用统一的一套接口,这样实现起来更简洁明了
  2. 复用了现有的类和代码,减少代码的改动量

使用场景

适配器模式是⽤来做适配的,它使得不兼容的接⼝转换为可兼容的接⼝,让原本由于接⼝不兼容⽽不能⼀起⼯作的类可以⼀起⼯作。常用于补偿接口设计上的缺陷。

一般使用场景如下:

  • 封装有缺陷的接⼝设计
  • 统⼀多个类的接⼝设计
  • 替换依赖的外部系统
  • 兼容⽼版本接⼝
  • 适配不同格式的数据

桥接模式

桥接模式是将抽象部分与他的具体实现分离,使其都可以独立的发生变化而互不干扰,属于结构型模式。
桥接模式的核心在于解耦抽象和实现。

这里的“抽象”,指的并⾮“抽象类”或“接⼝”,⽽是被抽象出来的⼀套“类库”,它只包含⾻架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。⽽定义中的“实现”,也并⾮“接⼝的实现类”,⽽是⼀套独⽴的“类库”。“抽象”和“实现”独⽴开发,通过对象之间的组合关系,组装在⼀起

经典的桥接模式的应用就是我们的JDBC驱动

{Class.forName("com.mysql.jdbc.Driver");//加载及注册JDBC驱动程序String url = "jdbc:mysql://localhost:3306/db?Connection con = DriverManager.getConnection(url);Statement stmt = con.createStatement()String query = "select * from test_table";ResultSet rs=stmt.executeQuery(query);while(rs.next()) {rs.getString(1);rs.getInt(2);}
}

如果我们使用不同的数据库,只需要将com.mysql.jdbc.Driver 换成 oracle.jdbc.driver.OracleDriver 就可以了

我们可以看下jdbc是怎么实现的

public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}

Class.forName("com.mysql.jdbc.Driver")这里就是执行了Driver的静态代码块,将Driver注册到DriverManager里,然后我们从DriverManager里获取的connection实际是使用我们注册的driver获取到的

 public static Connection getConnection(String url,java.util.Properties info) throws SQLException {return (getConnection(url, info, Reflection.getCallerClass()));}private static Connection getConnection(//...for(DriverInfo aDriver : registeredDrivers) {if(isDriverAllowed(aDriver.driver, callerCL)) {try {Connection con = aDriver.driver.connect(url, info);if (con != null) {// Success!println("getConnection returning " + aDriver.driver.getClass().getName());return (con);}} catch (SQLException ex) {if (reason == null) {reason = ex;}}} else {println("    skipping: " + aDriver.getClass().getName());}}throw new SQLException("No suitable driver found for "+ url, "08001");}

桥接模式主要包含四种角色
抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。

具体类图如下:
在这里插入图片描述
以日常工作种的告警为例,我们的告警消息可以是通过邮件,短信,电话的方式发送,根据告警的重要程度又可以分为紧急,重要,普通。告警消息可以按照发送方式和紧急程度两个不同的维度进行拆分

先定义一个发送消息的接口和一个桥接的抽象角色

public interface IMessageSender {void sendMessage(String message);
}
public abstract class AbstractMessage {private IMessageSender messageSender;public AbstractMessage(IMessageSender messageSender) {this.messageSender = messageSender;}public void sendMessage(String message) {this.messageSender.sendMessage(message);}
}
public class EmailMessageSender implements IMessageSender{@Overridepublic void sendMessage(String message) {System.out.println("发送邮件"+ message + ".....");}
}public class PhoneMessageSender implements IMessageSender{@Overridepublic void sendMessage(String message) {System.out.println("拨打电话:" + message + ".....");}
}public class SmsMessageSender implements IMessageSender{@Overridepublic void sendMessage(String message) {System.out.println("发送短信" + message + ".....");}
}
public class NormalMessage extends AbstractMessage{public NormalMessage(IMessageSender messageSender) {super(messageSender);}@Overridepublic void sendMessage(String message) {super.sendMessage("普通" + message);}
}
public class UrgencyMessage extends AbstractMessage {public UrgencyMessage(IMessageSender messageSender) {super(messageSender);}@Overridepublic void sendMessage(String message) {super.sendMessage("紧急" + message);}
}

总结

桥接模式适合于以下几个场景:

  1. 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
  2. 系统不希望使用继承或因为多层次继承导致类的个数急剧增加
  3. 需要在抽象和具体实现之间增加更多的灵活性

相关文章:

【设计模式】适配器模式和桥接模式

适配器模式 适配器模式 : 就是将一个类的接口变成客户端所期望的另一种接口,使得原本因为接口不匹配而无法一起工作的接口可以正常工作。属于结构型模式 比方说我有一个A牌子的奶瓶,然后买了个B牌子的奶嘴,不能匹配怎么办? 再买一个转换器…...

被隐藏的过程——预处理

文章目录0. 前言1. 程序的翻译环境和执行环境2. 被隐藏的过程2.1 翻译环境2.2 编译3.2.1 预编译3.2.2 编译2.2.3 汇编2.3 链接2.4 运行环境3. 预处理3.1 预定义符号3.2 #define3.2.1 #define定义标识符3.2.2 #define定义宏3.2.3 #define替换规则3.2.4 #和##3.2.5 带副作用的宏参…...

strace 用法介绍

strace 是什么 strace 是一个可用于诊断和调试的 Linux 用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。 strace 作为一种动态跟踪工具,能够帮助我们高效地定位进程和服务故障。它像是一个侦探&…...

TiDB数据库架构概述

文章目录TiDB体系架构TiDB ServerStorage Cluster(存储引擎)PD cluster题目TiDB体系架构 TiDB Server Sql语句最先到达 TiDB Server集群 它是无状态的,数据并不是存储在这里面,当一个会话连接到TiDB Server集群上,sql语句发过来&#xff0c…...

[深入理解SSD系列综述 闪存实战2.1.2] SLC、MLC、TLC、QLC、PLC NAND_固态硬盘闪存颗粒类型

闪存最小物理单位是 Cell, 一个Cell 是一个晶体管。 闪存是通过晶体管储存电子来表示信息的。在晶体管上加入了浮动栅贮存电子。数据是0或1取决于在硅底板上形成的浮动栅中是否有电子。有电子为0,无电子为1. SSD 根据闪存颗粒区分,固态硬盘有SLC、MLC、TLC、QLC、PLC 五种类型…...

游戏逆向之游戏技能分析

角色的当前技能列表往往都是从系统的技能库中进行筛选而组成的,而这个筛选的过程大多非常的复杂,经过的代码和临时结构体的传递也非常的多,所以在分析技能对象来源的时候常常要将OD和CE配合来使用。下面我们来分析下《天堂2》的技能列表。 首…...

汽车制造商与IT公司之间的技术合作案例

如果您对最新汽车技术感兴趣的话,您可能经常听到汽车制造商和IT公司正在合作开发技术的消息。汽车生产商为何自身不进行技术开发,而是与IT企业合作呢?因为最近随着以IT技术为基础的电动汽车等环保汽车或无人驾驶汽车等的登场和发展,汽车制造商单独进行技术开发需要花费很多时间…...

funkyheatmap | 用这个包来完美复刻Nature Biotechnology的高颜值神图吧!~

1写在前面 天气开始暖和了☀️,发现旅游的人好多啊!~🥲 不知道自己什么时候能有时间出去看看外面的世界,实在是太忙了。😷 最近用到的有个包感觉很不错,分享给大家,funkyheatmap包。&#x1f61…...

tomcat8调优

环境说明Jdk:1.8Tomcat: 8.5.69服务器 :2核 8G方案当调整Tomcat配置时,具体的配置方法可能会有所不同,因为它们受到许多因素的影响,例如Tomcat版本、操作系统、硬件配置等等。以下是每个建议的一些具体配置示例&#x…...

VS Code 解决 SpringBoot 项目启动时报 Failed to refresh live data from process **** 的问题

问题 SpringBoot 启动后 ,VS Code 报错 Failed to refresh live data from process ****。 现场是,SpringBoot 项目启动时,VS Code 将进行如下刷新,图片如下所示 当刷新 10 次以后,如果还是失败,则会抛出…...

[ 红队知识库 ] 各种重要文件路径

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

Ajax和JSON的基本用法

局部请求页面不会变化&#xff0c;返回的响应我们要动态获取&#xff0c;获取后选择数据更新区域。<body> <input id"btnLoad" type"button" value"加载"> <div id"divContent"></div> <script>//获取点…...

【项目实战】基于netty-websocket-spring-boot-starter实现WebSocket服务器长链接处理

一、背景 项目中需要建立客户端与服务端之间的长链接&#xff0c;首先就考虑用WebSocket&#xff0c;再来SpringBoot原来整合WebSocket方式并不高效&#xff0c;因此找到了netty-websocket-spring-boot-starter 这款脚手架&#xff0c;它能让我们在SpringBoot中使用Netty来开发…...

BC双驱、ChatGPT大火,AI独角兽撬开盈利大门?

配图来自Canva可画 放眼AI行业&#xff0c;各大AI玩家长期亏损、“钱”景堪忧。 回看过去一年&#xff0c;部分AI独角兽的亏损问题愈发尖锐——云从科技2022年净亏损同比扩大至8.5亿元&#xff1b;寒武纪2022年净亏损11.6亿元&#xff0c;较上年同期扩大41.4%&#xff1b;地平…...

1/4车、1/2车、整车悬架H2/H∞控制仿真合集

目录 前言 1. 1/4悬架系统 1.1数学模型 1.2 H2/H∞求解反馈阵阵 1.3仿真分析 2. 1/2悬架系统 2.1数学模型 2.2 H2/H∞求解反馈阵阵 2.3仿真分析 3. 整车悬架系统 3.1数学模型 整车7自由度主动悬架数学模型 3.2 H2/H∞求解反馈阵阵 3.3仿真分析 4.总结 参考文献 …...

Git使用教程、命令

Git使用教程、命令 基本配置 git的配置文件位置&#xff1a; win: c:\users\<userName>\.gitconfig linux: /home/<userName>/.gitconfig # 个人/etc/gitconfig # 系统全局# 修改git init时的默认分支为master&#x…...

《c++ primer笔记》第九章 顺序容器

前言 知识点很多&#xff0c;这里只记录遗忘的。从这章开始会对前面章节的内容进行一个扩充&#xff0c;如果以前的忘了读起来会有点吃力。总的来说&#xff0c;本章节难度不大。 文章目录一、概述二、容器库概览2.1容器定义和初始化2.2赋值三、顺序容器操作3.1添加元素3.2删除…...

QML动画(弹动和翻转效果)

Flickable&#xff08;弹动&#xff09; QML中提供了一个Flickable元素&#xff0c;可以将其子项设置在一个可以拖拽和弹动的界面上&#xff0c;使得子项目的视图可以滚动。在传统的用户界面中&#xff0c;可以使用标准控件&#xff08;如滚动条和箭头按钮&#xff09;滚动视图…...

GPS启动方式、定位速度、定位精度介绍

前面文章介绍了GPS定位基础知识 GPS定位知识介绍 (qq.com) 本文主要介绍GPS启动方式。 定位过程中最重要的辅助信息是时间、星历、位置。 根据辅助信息不同,...

深度学习零基础学习之路——第五章 个人数据集的制作

Python深度学习入门 第一章 Python深度学习入门之环境软件配置 第二章 Python深度学习入门之数据处理Dataset的使用 第三章 数据可视化TensorBoard和TochVision的使用 第四章 UNet-Family中Unet、Unet和Unet3的简介 第五章 个人数据集的制作 深度学习数据集的制作Python深度学…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...