【设计模式】适配器模式和桥接模式
适配器模式
适配器模式 : 就是将一个类的接口变成客户端所期望的另一种接口,使得原本因为接口不匹配而无法一起工作的接口可以正常工作。属于结构型模式
比方说我有一个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;}
}
接口适配器 : 如果接口定义的方法过多,通过接口适配器可以让我们只实现需要转换的方法(直接实现接口的话就会有很多空实现的方法)
总结
优点 :
- 通过适配器模式,客户端可以使用统一的一套接口,这样实现起来更简洁明了
- 复用了现有的类和代码,减少代码的改动量
使用场景
适配器模式是⽤来做适配的,它使得不兼容的接⼝转换为可兼容的接⼝,让原本由于接⼝不兼容⽽不能⼀起⼯作的类可以⼀起⼯作。常用于补偿接口设计上的缺陷。
一般使用场景如下:
- 封装有缺陷的接⼝设计
- 统⼀多个类的接⼝设计
- 替换依赖的外部系统
- 兼容⽼版本接⼝
- 适配不同格式的数据
桥接模式
桥接模式是将抽象部分与他的具体实现分离,使其都可以独立的发生变化而互不干扰,属于结构型模式。
桥接模式的核心在于解耦抽象和实现。
这里的“抽象”,指的并⾮“抽象类”或“接⼝”,⽽是被抽象出来的⼀套“类库”,它只包含⾻架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。⽽定义中的“实现”,也并⾮“接⼝的实现类”,⽽是⼀套独⽴的“类库”。“抽象”和“实现”独⽴开发,通过对象之间的组合关系,组装在⼀起
经典的桥接模式的应用就是我们的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);}
}
总结
桥接模式适合于以下几个场景:
- 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
- 系统不希望使用继承或因为多层次继承导致类的个数急剧增加
- 需要在抽象和具体实现之间增加更多的灵活性
相关文章:
【设计模式】适配器模式和桥接模式
适配器模式 适配器模式 : 就是将一个类的接口变成客户端所期望的另一种接口,使得原本因为接口不匹配而无法一起工作的接口可以正常工作。属于结构型模式 比方说我有一个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语句发过来,…...
[深入理解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包。ὡ…...
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的基本用法
局部请求页面不会变化,返回的响应我们要动态获取,获取后选择数据更新区域。<body> <input id"btnLoad" type"button" value"加载"> <div id"divContent"></div> <script>//获取点…...
【项目实战】基于netty-websocket-spring-boot-starter实现WebSocket服务器长链接处理
一、背景 项目中需要建立客户端与服务端之间的长链接,首先就考虑用WebSocket,再来SpringBoot原来整合WebSocket方式并不高效,因此找到了netty-websocket-spring-boot-starter 这款脚手架,它能让我们在SpringBoot中使用Netty来开发…...
BC双驱、ChatGPT大火,AI独角兽撬开盈利大门?
配图来自Canva可画 放眼AI行业,各大AI玩家长期亏损、“钱”景堪忧。 回看过去一年,部分AI独角兽的亏损问题愈发尖锐——云从科技2022年净亏损同比扩大至8.5亿元;寒武纪2022年净亏损11.6亿元,较上年同期扩大41.4%;地平…...
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的配置文件位置: win: c:\users\<userName>\.gitconfig linux: /home/<userName>/.gitconfig # 个人/etc/gitconfig # 系统全局# 修改git init时的默认分支为master&#x…...
《c++ primer笔记》第九章 顺序容器
前言 知识点很多,这里只记录遗忘的。从这章开始会对前面章节的内容进行一个扩充,如果以前的忘了读起来会有点吃力。总的来说,本章节难度不大。 文章目录一、概述二、容器库概览2.1容器定义和初始化2.2赋值三、顺序容器操作3.1添加元素3.2删除…...
QML动画(弹动和翻转效果)
Flickable(弹动) QML中提供了一个Flickable元素,可以将其子项设置在一个可以拖拽和弹动的界面上,使得子项目的视图可以滚动。在传统的用户界面中,可以使用标准控件(如滚动条和箭头按钮)滚动视图…...
GPS启动方式、定位速度、定位精度介绍
前面文章介绍了GPS定位基础知识 GPS定位知识介绍 (qq.com) 本文主要介绍GPS启动方式。 定位过程中最重要的辅助信息是时间、星历、位置。 根据辅助信息不同,...
深度学习零基础学习之路——第五章 个人数据集的制作
Python深度学习入门 第一章 Python深度学习入门之环境软件配置 第二章 Python深度学习入门之数据处理Dataset的使用 第三章 数据可视化TensorBoard和TochVision的使用 第四章 UNet-Family中Unet、Unet和Unet3的简介 第五章 个人数据集的制作 深度学习数据集的制作Python深度学…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
