Java进阶篇设计模式之四 -----适配器模式和桥接模式

ops/2024/10/30 15:43:07/

前言

在上一篇中我们学习了创建型模式的建造者模式和原型模式。本篇则来学习下结构型模式的适配器模式和桥接模式。

适配器模式

简介

适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

简单的来说就是通过某个接口将不兼容的两个类进行兼容,俗称转换器。
生活比较典型的例子是电器的电压,美国的电压是110V左右, 而中国的电压普片是220V,如果我们想用美国或日本的电器,则需要一个转换器,将110V转换成220V。还有一个很典型例子就是曾经的万能充,基本可以充各种手机的电池。

这里我们用一个简单的示例来进行说明。
某个视频播放器,只能播放MP4格式的视频,但是主流的视频格式除了MP4,还有AVI、RVMB等,这时就有个软件,格式工厂用于对视频格式的转换(适配器),从而进行播放视频。这时我们就可以使用适配器模式来进行完成该代码的编写。

适配器模式主要有两种类型,一种是类适配器模式,主要通过继承来实现适配器功能;一种是对象适配器模式,通过组合来实现适配器功能。

首先是适配器模式,它需要完成一下步骤:

  1. 建立MP4、AVI、RVMB视频格式的接口;
  2. 建立一个视频播放器的类实现MP4视频格式的类;
  3. 编写一个格式工厂类,将AVI、RVMB等格式的视频文件转换成MP4格式的文件。
  4. 播放这些视频。

那么代码如下:

代码示例:

interface Mp4{void playMp4();}interface Avi{void playAvi();}interface Rvmb{void playRvmb();}class VideoPlayer implements Mp4{@Overridepublic void playMp4() {System.out.println("播放Mp4格式的视频文件.");}}class FormatFactory extends VideoPlayer  implements Avi{	@Overridepublic void playAvi() {//转换成MP4格式的视频playMp4();}}public static void main(String[] args) {		Mp4 mp4=new VideoPlayer();mp4.playMp4();Avi avi=new FormatFactory();avi.playAvi();}

运行结果:

	播放Mp4格式的视频文件.播放Mp4格式的视频文件.

通过上述代码以及运行结果,我们可以得到想要的结果了,如果还有新增的视频格式,也需要使用该视频播放器播放的话,只需在增加一个接口以及格式工厂类就可以了。

对象适配器模式
通过组合来实现适配器功能。
所以这里我们只需将格式工厂中继承改为创建对象即可。
更改之后的代码如下:
代码示例


class FormatFactory2  implements Rvmb{private Mp4 mp4;public FormatFactory2(Mp4 mp4) {this.mp4=mp4;}@Overridepublic void playRvmb() {mp4.playMp4();}	}public static void main(String[] args) {Rvmb rvmb=new FormatFactory2(new VideoPlayer());rvmb.playRvmb();}

运行结果:

	播放Mp4格式的视频文件.

这两种适配器模式中,都实现了该功能,不过在这里推荐使用对象适配器模式,相比适配器模式,它更加灵活,也符合设计原则中的合成复用原则:

尽量使用合成/聚合的方式,而不是使用继承。

适配器模式的优点:

提升了类的复用和灵活度。

适配器模式的缺点:

使用过多,系统会比较杂乱,难以把握。

注意事项:

适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

桥接模式

简介

桥接是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

字面的意思解读就是通过一个中间的桥梁对两边的东西进行关联起来,但是关联的两者之间又不相互影响。对这个印象比较深的是<大话设计模式>中的手机品牌和手机软件,手机有很多品牌,市场有很多软件,每个手机装的软件又各不相同,手机品牌包含包含软件,但是软件并不是手机的一部分,它们是聚合关系。如果A品牌手机装了a,b软件,B品牌手机装了b,c软件,如果A品牌手机需要新安装一个c软件,那么它只需添加该软件即可,无需知道该软件是如何生产的。相同的,如果新增了一个C品牌手机,那么它也只需安装所需的a、b或c软件即可。

好了,废话不在多说,依旧用一个示例来进行说明。
市面上有很多种笔,比如铅笔、黑色的圆珠笔和红色的圆珠笔等等, 也有很多种类型的纸,比如考试的卷子用的纸,报纸用的纸等等。一般来说,报纸上的字颜色是黑色的,这里我们就用黑色的圆珠笔来进行书写,考试卷子上的打分字颜色是红色的,这里我们就用红色的圆珠笔来进行书写。笔类和纸类相互独立,但是在纸上写字又将它们关联起来,这里我们就可以使用桥接模式。

实现步骤如下:

  1. 定义一个笔类的接口,有写的这个方法;
  2. 定义红笔和黑笔的类,实现笔类的接口;
  3. 定义一个纸类的抽象类,设置笔的种类,并需要实现被写的方法;
  4. 定义卷子纸和新闻纸类,继承纸类并实现该方法;
  5. 进行书写。

代码示例


interface Pen{void write();
}class RedPen implements Pen{@Overridepublic void write() {System.out.println("红色的字");}
}class BlackPen implements Pen{@Overridepublic void write() {System.out.println("黑色的字");}
}abstract class  Paper{protected  Pen pen;void setPen(Pen pen){this.pen=pen;}	abstract void writing();
}class ExaminationPaper extends Paper{@Overridevoid writing() {pen.write();}
}class NewsPaper extends Paper{@Overridevoid writing() {pen.write();}
}public static void main(String[] args) {Paper paper=new ExaminationPaper();paper.setPen(new RedPen());paper.writing();Paper paper2=new NewsPaper();paper2.setPen(new BlackPen());paper2.writing();}

运行结果

红色的字
黑色的字

从上述结果中我们可以得出我们想要的结果。如果新增一个笔类或者一个纸类,那么只需新增相应的接口和实现即可,并不会因为结构化改变而相互直接影响。

桥接模式的优点:

1、抽象和实现的分离,实现了解耦;
2、提升的扩展能力。

桥接模式的缺点:

会使系统看起复杂,对新手不友好,没有一定的抽象进行设计能力难以理解。

使用场景:

一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。


http://www.ppmy.cn/ops/129621.html

相关文章

Spring 全家桶新人入门指南:服务调用最佳实践

spring 全家桶的整体介绍 Spring 全家桶提供了一整套解决方案&#xff0c;覆盖了从基础框架到企业级应用开发的各个方面。其中&#xff0c;Spring Boot 旨在简化新 Spring 应用的初始搭建以及开发过程&#xff0c;通过约定大于配置的原则来快速启动项目&#xff1b;Spring MVC…

巴西电商市场神仙打架,美客多多月蝉联访问量榜首,9月Temu位居巴西APP下载量榜首

巴西电商市场近年来呈现出强劲的增长趋势&#xff0c;预计2024年巴西电子商务市场的销售额将达到2043亿雷亚尔&#xff08;约合373亿美元&#xff09;&#xff0c;同比增长约10%。作为拉美地区最大的经济体&#xff0c;巴西吸引了众多电商平台和商家&#xff0c;巴西电商市场竞…

Hyperledger Fabric有那些核心技术,和其他区块链对比Hyperledger Fabric有那些优势

Hyperledger Fabric是一个模块化、权限化的企业级区块链平台&#xff0c;与比特币、以太坊等公有链相比&#xff0c;Fabric主要为私有链或联盟链设计&#xff0c;适用于企业应用。它包含多项核心技术&#xff0c;使其在企业级区块链应用中具有独特优势。以下是Fabric的核心技术…

Android Studio获取本地aar,最新依赖jar/aar

每次清缓存后打开Android Studio的项目都要加载依赖库很久&#xff0c;那是网络要下载 依赖库和各种指针索引构建&#xff0c;本文提供获取本地依赖库的aar方法&#xff0c;然后把aar以libs的包本地方式引入&#xff0c;减少网络下载&#xff0c;会把kts和groovy的代码都展示。…

分布式项目pom配置

1. 父项目打包方式为 pom <packaging>pom</packaging> 2. 父项目版本配置 <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncod…

机器学习实战——基于随机森林与决策树模型的贷款违约预测全过程(附完整代码和可视化分析)

机器学习实战——基于随机森林与决策树模型的贷款违约预测全过程&#xff08;附完整代码和可视化分析&#xff09; 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机器视觉&#…

使用 undici 为 Node.js 原生 fetch 请求设置代理

在 Node.js 项目中&#xff0c;有时需要通过代理服务器发送 HTTP 请求。然而&#xff0c;许多第三方库&#xff08;如原生 fetch&#xff09;无法直接支持 https-proxy-agent 或 socks-proxy-agent 等代理库。在这种情况下&#xff0c;可以通过 undici 提供的全局调度器为请求设…

从三方云服务器将数据迁移至本地,如何保障安全高效?

前言 在数字化时代&#xff0c;企业越来越多地依赖云服务来存储和管理数据。然而&#xff0c;随着业务的发展和需求的变化&#xff0c;企业有时需要将数据从第三方云服务器迁移到本地。这一过程不仅涉及大量的数据传输&#xff0c;还需要确保数据的安全性和迁移的高效性。本文…