设计模式——适配器模式

引入实例

说起适配器其实在我们的生活中是非常常见的,比如:学校的宿舍的电压都比较低,而有的学生想使用大功率电器,宿舍的就会跳闸,然而如果你使用一个适配器(变压器)就可以使用了(温馨提示宿舍使用大功率电器不太安全,容易引起火灾,希望大家谨慎使用)。

又比如说,有的插座都是三孔的,而我们用的大部分电器是两孔的,这时我们可以使用一个适配器,适配器本身是三孔的,它可以直接插到三孔的插头上,适配器本身可以提供一个两孔的插座,然后我们就可以插到适配器上了,这样我们原本只能插到两孔上的插头就能用三孔的插座了。

适配器模式的相关概念

适配器模式的正式定义

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

适配器模式分为

  • 类适配器模式
  • 对象适配器模式

适配器模式的结构

适配器模式里面总共拥有三个角色,它们分别是:

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

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

类适配器

类适配器的原理就是通过继承来实现适配器功能。

让Adapter实现Target接口,并且继承Adaptee,这样Adapter就具备Target和Adaptee的特性,就可以将两者进行转化。

举例:以不同设备使用不同交流电为例,通过电源适配器进行转换说明。

创建目标角色(Target)

public interface Target {int out();
}

创建源角色(Adaptee)

public class Adaptee{public int input() {System.out.println("输入交流电: 220V");return 220;}
}

创建适配器(Adapter)

public class Adapter extends Adaptee implements Target {@Overridepublic int out() {int input220V = super.input();int output = input220V / 2;System.out.println("输出交流电: " + output + "V");return output;}
}

客户端调用

public static void main(String[] args) {Target adapter = new Adapter();int result = adapter.out();System.out.println(result);
}

输入交流电: 220V
输出交流电: 110V
110

对象适配器

对象适配器的原理就是通过组合来实现适配器功能。

让Adapter实现Target接口,然后内部持有Adaptee实例,然后再Target接口规定的方法内转换Adaptee。

创建目标角色(Target)

public interface Target {int out();
}

创建源角色(Adaptee)

public class Adaptee{public int input() {System.out.println("输入交流电: 220V");return 220;}
}

创建适配器(Adapter)

public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic int out() {int output = adaptee.input() / 2;System.out.println("输出交流电: " + output + "V");return output;}
}

客户端调用

    public static void main(String[] args) {Target adapter = new Adapter(new Adaptee());int result = adapter.out();System.out.println(result);}

输入交流电: 220V
输出交流电: 110V
110

接口适配器

接口适配器的使用场景是解决接口方法过多,如果直接实现接口,那么类会多出许多空实现的方法,类显得很臃肿。此时,使用接口适配器就能让我们只实现我们需要的接口方法,目标更清晰。

接口适配器的主要原理就是原理利用抽象类实现接口,并且空实现接口众多方法。

创建目标角色(Target)

public interface Target {int out1();int out2();int out3();int out4();
}

创建源角色(Adaptee)

public class Adaptee{public int input() {System.out.println("输入交流电: 220V");return 220;}
}

创建适配器(Adapter)

public class Adapter implements Target {protected Adaptee adaptee;public Adapter(Adaptee adaptee){this.adaptee = adaptee;}@Overridepublic int out1() {int input220V = adaptee.input();int output = input220V / 1;System.out.println("输出交流电: " + output + "V");return output;}@Overridepublic int out2() {int input220V = adaptee.input();int output = input220V / 2;System.out.println("输出交流电: " + output + "V");return output;}@Overridepublic int out3() {return 0;}@Overridepublic int out4() {return 0;}
}

客户端调用

    public static void main(String[] args) {Target adapter = new Adapter(new Adaptee());adapter.out1();System.out.println("---------------------");adapter.out2();System.out.println("---------------------");Target adapter2 = new Adapter(new Adaptee()) {@Overridepublic int out3() {int input220V = adaptee.input();int output = input220V / 3;System.out.println("输出交流电: " + output + "V");return output;}};adapter2.out3();System.out.println("---------------------");Target adapter3 = new Adapter(new Adaptee()) {@Overridepublic int out4() {int input220V = adaptee.input();int output = input220V / 4;System.out.println("输出交流电: " + output + "V");return output;}};adapter3.out4();}

输入交流电: 220V
输出交流电: 220V
---------------------
输入交流电: 220V
输出交流电: 110V
---------------------
输入交流电: 220V
输出交流电: 73V
---------------------
输入交流电: 220V
输出交流电: 55V

优缺点

适配器模式优点:

  • 可以让任何两个没有关联的类一起运行。
  • 提高了类的复用。
  • 增加了类的透明度。
  • 灵活性好。

适配器模式缺点:

  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
  • 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

优点 :

  • 类适配器模式优点:由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
  • 对象适配器模式优点:一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

缺点:

  • 类适配器模式缺点:对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
  • 对象适配器模式缺点:与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。

类适配器和对象适配器的区别:

  • 前者类之间的耦合度比后者高(这是因为类适配器模式使用的是继承的方式,而对象适配器模式使用的是聚合或者组合的方式)。
  • 类适配器模式要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些,用的更多的还是对象适配器模式。

应用场景

  1. 当一个系统需要使用另一个系统的接口时,但是两个系统的接口不兼容,可以使用适配器模式进行接口转换。
  2. 在数据处理方面,适配器模式可以用于将不同格式的数据适配到一个标准的数据格式上。
  3. 当我们需要复用一些已有的类的时候,这些类的接口与我们需要的接口不兼容,可以使用适配器将这些类的接口转换成我们需要的接口,从而实现类的复用。
  4. 适配器模式可以用于封装有缺陷的接口设计,使得客户可以通过适配器来使用这些缺陷的接口,而无需直接与其交互。
  5. 替换依赖的外部系统,使得系统可以在不修改源代码的情况下适应新的外部系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/73869.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++进阶】继承、多态的详解(多态篇)

【C进阶】继承、多态的详解(多态篇) 目录 【C进阶】继承、多态的详解(多态篇)多态的概念多态的定义及实现多态的构成条件(重点)虚函数虚函数的重写(覆盖、一种接口继承)C11 override…

安卓的代码加固和其他安全问题

文章目录 安卓加固apk文件结构dex加固过程 其它安全问题 安卓加固 从App的加固技术来看:主流分为dex加密和so加密,目前来看保护dex文件更为重要,因为dex反编译后的java代码可读性更强。 android-ndk: Native Development Kit 官网解释:这套工具使您能在 Android 应…

STM32F407使用Helix库软解MP3并通过DAC输出,最精简的STM32+SD卡实现MP3播放器

只用STM32单片机SD卡耳机插座,实现播放MP3播放器! 看过很多STM32软解MP3的方案,即不通过类似VS1053之类的解码器芯片,直接用STM32和软件库解码MP3文件,通常使用了labmad或者Helix解码库实现,Helix相对labm…

揭秘程序员的鄙视链,你在哪一层?看完我想哭

虽然不同的编程语言都有其优缺点,而且程序员之间的技能和能力更加重要,但是有些程序员可能会因为使用不同的编程语言而产生鄙视链。 以下是一些可能存在的不同编程语言程序员之间的鄙视链: 低级语言程序员鄙视高级语言程序员:使用…

Ubuntu常用配置

文章目录 1. 安装VMware虚拟机软件2. 下载Ubuntu镜像3. 创建Ubuntu虚拟机4. 设置屏幕分辨率5. 更改系统语言为中文6. 切换中文输入法7. 修改系统时间8. 修改锁屏时间9. 通过系统自带的应用商店安装软件10. 安装JDK11. 安装 IntelliJ IDEA12. 将左侧任务栏自动隐藏13. 安装docke…

.netcore grpc身份验证和授权

一、鉴权和授权(grpc专栏结束后会开启鉴权授权专栏欢迎大家关注) 权限认证这里使用IdentityServer4配合JWT进行认证通过AddAuthentication和AddAuthorization方法进行鉴权授权注入;通过UseAuthentication和UseAuthorization启用鉴权授权增加…

在 React+Typescript 项目环境中创建并使用组件

上文 ReactTypescript清理项目环境 我们将自己创建的项目环境 好好清理了一下 下面 我们来看组件的创建 组件化在这种数据响应式开发中肯定是非常重要的。 我们现在src下创建一个文件夹 叫 components 就用他专门来处理组件业务 然后 我们在下面创建一个 hello.tsx 注意 是t…

架构演进及常用架构

1架构演进及常用架构 1.1单体分层架构 1.2 多应用微服务架构 1.3 分布式集群部署 部署 CDN 节点: 用户访问量的增加意味着用户地域的分散请求,如果所有请求都直接发送中心服务器的话,距离越远,响应速度越差,这时就需…

使用CLI添加磁盘到VM

登录 https://portal.azure.com/#home,点击右上角的控制台图标 ,打开CLI 在控制台中输入如下指令,在NetworkWatcherRG创建一个名字为TEST的虚拟机,使用的镜像是Win2019datacenter,username是aaa,password是1234567890A…

Go语言基础之基本数据类型

Go语言中有丰富的数据类型,除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。Go 语言的基本类型和其他语言大同小异。 基本数据类型 整型 整型分为以下两个大类: 按…

javascript期末作业【三维房屋设计】

1、引入three.js库 官网下载three.js 库 放置目录并引用 引入js文件: 设置场景(scene) (1)创建场景对象 (2)设置透明相机 1,透明相机的优点 透明相机机制更符合于人的视角,在场景预览和游戏场景多有使用…

BIO、NIO和AIO

一.引言 何为IO 涉及计算机核心(CPU和内存)与其他设备间数据迁移的过程,就是I/O。数据输入到计算机内存的过程即输入,反之输出到外部存储(比如数据库,文件,远程主机)的过程即输出。 I/O 描述了计算机系统…