当前位置: 首页 > 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深度学…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...