设计模式之适配器模式

news/2024/11/22 22:37:22/

目录

1、什么是适配器模式

2、为什么用适配器模式

3、适配器模式的结构

4、类适配器模式代码实现

4.1 思想

4.2 代码实现

4.3 问题分析 

5、对象适配器模式代码实现

5.1 思想

5.2 代码实现

6、适配器模式应用场景


1、什么是适配器模式

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

适配器模式能够将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,要求程序员了解现有组件库中的相关组件的内部结构,且前者不符合我们六大软件设计原则中的“合成复用原则”,所以应用相对较少些。

2、为什么用适配器模式

举个很简单的例子:大家在之前的时候,会发现耳机孔是那种圆圆的耳机孔,但是发展到后来,大部分手机取消了这种圆圆的耳机孔(图一),取而代之的是将耳机头改为Type-C头(图二),和充电口共用一个口。但是如果我们这个时候想用那种圆圆的耳机孔的话,只能通过“转接头”(图三)来使用。这个转接头便是“适配器”思想。

图一

 图二

图三 

3、适配器模式的结构

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

接下来我们会利用上述例子来讲解适配器类的实现。例子:有一部手机,只支持Type-C接口的耳机,但是我们现在拥有的是圆口耳机,因此只能用转换器来使得我们的手机能够使用圆口耳机。

4、类适配器模式代码实现

4.1 思想

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

4.2 代码实现

Type-C耳机接口:

public interface TypeCEarPhone { //Type-C耳机接口public void type();//表名自己是什么类型
}

 Type-C口耳机的实现类:

public class TypeCEarPhoneImpl implements TypeCEarPhone { //Type-C口耳机的实现类@Overridepublic void type() {System.out.println("我是Type-C口的耳机");}
}

 圆口耳机接口:

public interface CircularEarPhone { //圆口耳机接口public void type();//表名自己是什么类型
}

圆口耳机的实现类:

public class CircularEarPhoneImpl implements CircularEarPhone { //圆口耳机的实现类@Overridepublic void type() {System.out.println("我是圆口的耳机");}
}

手机类:

public class Phone { //手机类public void useEarPhone(TypeCEarPhone earPhone){ //只支持Type-C接口的耳机earPhone.type();//表明自己现在是什么耳机类型}
}

测试类:

public class Test {public static void main(String[] args) {Phone phone = new Phone(); //new一个手机对象CircularEarPhoneImpl earPhone = new CircularEarPhoneImpl();//此时我只有一个圆口耳机phone.useEarPhone(earPhone); //手机来使用耳机}
}

大家会发现,上述代码会报错: 

因为我们手机仅支持Type-C口的,因此这里我们肯定无法使用圆口的耳机,因此这个时候就需要使用“转换器”来使得我们手机能够使用这个耳机了。

转换器类:

public class Adapter extends CircularEarPhoneImpl implements TypeCEarPhone {@Overridepublic void type() {super.type();}
}

这个时候我们再来通过转换类使用耳机即可:

public class Test {public static void main(String[] args) {Phone phone = new Phone(); //new一个手机对象Adapter earPhone = new Adapter();//由于转换器类继承了耳机类,相当于耳机和转换器直接连一起了phone.useEarPhone(earPhone); //手机来使用耳机}
}

运行结果如下:

4.3 问题分析 

可见,上述我们通过“转换器”成功让我们仅支持Type-C接口的手机使用上了圆口的耳机。这种方式比较简单粗暴,直接相当于将“耳机和转换器”连接到一起使用,但是缺点很明显:耦合性太大,如果此时我们想使用的是另一个圆口耳机类,是不是就不太行了?因此我们更推荐大家使用接下来这种实现方式:对象适配器模式。当然这种方式也是更符合我们“合成复用原则”的一种实现方式。

5、对象适配器模式代码实现

5.1 思想

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

5.2 代码实现

这里我们手机类、圆口耳机接口、圆口耳机接口实现类、Type-C耳机接口、Type-C耳机接口实现类均和上述代码一样。唯一有变化的便是适配器类。

适配器类:

public class Adapter implements TypeCEarPhone {private CircularEarPhone earPhone;public Adapter(CircularEarPhone circularEarPhone){earPhone=circularEarPhone;}@Overridepublic void type() {earPhone.type();}
}

测试类:

public class Test {public static void main(String[] args) {Phone phone = new Phone(); //new一个手机对象CircularEarPhoneImpl circularEarPhone = new CircularEarPhoneImpl();//我们拥有的圆口耳机Adapter adapter = new Adapter(circularEarPhone);//将圆口耳机装上"转换器"phone.useEarPhone(adapter); //手机来使用耳机}
}

运行结果:

可见,这种“对象适配器模式”大大减少了我们适配器和耳机的耦合度,如果此时我们拥有的是另一种圆口类型的耳机,直接传参即可,因此我们更推荐大家使用这种适配器模式。

6、适配器模式应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

http://www.ppmy.cn/news/61047.html

相关文章

实在智能出席第六届数字中国建设峰会,入围2022年信息技术应用创新优秀解决方案榜单

最美榕城四月天,山海之间尽显数字澎湃。这一周来,实在智能来到了“有福之州”,为数字中国建设增添实在色彩。 4月25日,实在华夏行抵达福州站,与众多生态合作伙伴携手共话数字发展新未来; 4月26日&#xff…

Android 11 WebView无法加载libwebviewchromium.so

概述 Android WebView 是 Google 提供的一个预安装系统组件,用以支持 Android 应用显示网页内容。 如果您希望在客户端应用中提供 Web 应用(或只是网页),则可以使用 WebView 执行该操作。WebView 类是 Android 的 View 类的扩展&a…

要么转型升级,要么躺平出局,IT人如何找到理想职场?

‍ ‍某位哲学家曾说:“工作的最高意义在于它应该是人类的仆人,而非主人”,但是在今年的就业环境下,大部分打工人嘴上喊着躺平,身体却很诚实地在行动上打鸡血。 但是卷起来就安全了吗?35岁之前走上管理岗就…

SpringBoot整合Mybatis实现商品评分

前言 当今的电商平台越来越依赖于用户评分,以确定一个商品在市场中的竞争力和口碑,而SpringBoot整合Mybatis-plus是非常适用于这一功能的框架。本文将介绍在SpringBoot应用中整合Mybatis-plus框架,实现对商品进行评分功能的实现过程。同时&a…

Db2 hardcode一个CTE

环境 DB2 v11.5.0.0 CTE &#xff08;Common Table Expression&#xff09; 基本用法 例如&#xff1a; with temp1 as (select * from t1 where c1 > 1) select * from temp1 where c2 < 100可见&#xff0c;定义好CTE之后&#xff0c;就可以当成table一样直接用了…

【python】【质量警告】提升代码质量

在提交代码时遇到了一些警告 &#xff08;没有写知道不能这么干的代码&#xff09;&#xff1a; 使用SQL语句查询时有填入的参数 Possible SQL injection vector through string-based query construction. 通过基于字符串的查询构造可能的SQL注入向量。 谨慎使用exec Use of e…

Spring的第十二阶段(03):Spring实现AOP的简单使用

1、获取拦截方法的返回值和抛的异常信息 获取方法返回的值分为两个步骤&#xff1a; 1、在返回值通知的方法中&#xff0c;追加一个参数 Object result 2、然后在AfterReturning注解中添加参数returning“参数名” 获取方法抛出的异常分为两个步骤&#xff1a; 1、在异常通…

【力扣周赛】第344场周赛

【力扣周赛】第344场周赛 6416&#xff1a;找出不同元素数目差数组题目描述解题思路 6417&#xff1a;频率跟踪器题目描述解题思路 6418&#xff1a;有相同颜色的相邻元素数目题目描述解题思路 6419&#xff1a;使二叉树所有路径值相等的最小代价题目描述解题思路 6416&#xf…