文章目录

  • 1 适配器模式介绍
  • 2 适配器模式详解
    • 2.1 适配器模式结构
    • 2.2 适配器模式实现
      • 2.2.1 类适配器
      • 2.2.2 对象适配器
    • 2.3 适配器模式应用举例
  • 3 缺省适配器模式
  • 4 双向适配器

1 适配器模式介绍

在现实生活中生活用电220V和笔记电脑20V不兼容,我们需要引入 AC Adapter(交流电适配器),在软件开发中我们也会存在不兼容的结构,这个时候就需要引入适配器模式。

适配器模式(Adapter Pattern)可以将一个类的接口和另一个类的接口匹配起来,而无需修改原来的适配者接口和抽象目标接口。

它将一个类的接口转换称客户希望的另一个接口,让那些接口不兼容的类可以一起工作。

适配器模式的别名为包装器模式(Wrapper Pattern),它既可以作为类结构模式,也可以作为对象结构型模式。在适配器模式的定义中所提及的接口是指广义的接口,它可以表示为方法或者方法的集合。

主要解决: 主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

如何解决: 继承或依赖(推荐)。

关键代码: 适配器继承或依赖已有的对象,实现想要的目标接口。

应用实例: 1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。 2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。 3、在 LINUX 上运行 WINDOWS 程序。 4、JAVA 中的 jdbc。

优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。

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

使用场景: 有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

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

2 适配器模式详解

2.1 适配器模式结构

类适配器模式的结构图如下:

对象适配器模式的结构图如下:

由上图可知,适配器模式包含以下3个角色。

  1. Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类或者接口,也可以是具体类。在类适配器中,由于Java语言不支持多重继承,它只能是接口。
  2. Adapter(适配器类):它可以调用另一个接口 ,作为一个转换器,对Adaptee和Target进行适配。适配器Adapter是适配器模式的核心,在类适配器中,它通过实现Target接口并继承Adaptee类来使二者产生联系,在对象适配器中,它通过继承Target并关联一个Adaptee对象来使二者产生联系。
  3. Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体的类,包含了客户希望使用的业务方法,在某些情况下甚至没有适配者类的代码。

2.2 适配器模式实现

2.2.1 类适配器

根据上图,在类适配器中适配者类Adaptee没有request方法,而客户端期待这个方法,但在适配者类中实现了specificRequest()方法,该方法提供的实现正式客户端所需要的。为了使客户端能够使用适配者类,提供了一个中间类,即适配器类Adapter,适配器类实现了抽象目标类接口Target,并继承了适配者类,在适配器类的request()方法中调用所继承的适配者类的specificRequest()方法,达到了适配的目的。

因为适配器类与适配者类使继承关系,所以这种适配器模式称为类适配器模式。典型的类适配器代码如下:

public class Adapter extends Adaptee implements Target {public void request() {super.specificRequest();}
}

2.2.2 对象适配器

根据上图,在对象适配器中适配者类Adaptee没有request方法,而客户端期待这个方法,但在适配者类中实现了specificRequest()方法,该方法提供的实现正式客户端所需要的。为了使客户端能够使用适配者类,需要提供一个包装类Adapter,即适配器类。

这个包装类包装了一个适配者的实例,从而将客户端与适配者衔接起来,在适配器的request()方法中调用适配者的specificRequest()方法。

因为适配器类与适配者类是关联关系,所以这种适配器模式称为对象适配器模式。典型的对象适配器代码如下:

public class Adapter extends Target {// 维持一个对适配者对象的引用private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {// 转发调用adaptee.specificRequest();}
}

2.3 适配器模式应用举例

  • 题目描述

    某公司欲开发一款儿童玩具汽车,为了更好地吸引小朋友的注意力,该玩具汽车在移动过程中伴随着灯光闪烁和声音提示。在该公司以往的产品中已经实现了控制灯光闪烁(例如警灯闪烁)和声音提示(例如警笛音效)的程序,为了重用先前的代码并且使得汽车控制软件具有更好的灵活性和扩展性,现使用适配器模式设计该玩具汽车控制软件。

  • UML类图

    使用对象适配器模式来实现,其UML类图如下:

    其中,CarController类充当抽象目标,PoliceSound和PoliceLamp类充当适配者,PoliceCarAdapter充当适配器。

  • 代码

    代码地址

3 缺省适配器模式

缺省适配器模式(Default Adapter Pattern):当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求,它适用于不想使用一个接口中的所有方法的情况,又称为单接口适配器模式。其结构图如下:

由上图可知,在缺省适配器模式中包含以下3个角色:

  1. ServiceInterface(适配者接口):它是一个接口,通常在接口中声明了大量的方法。
  2. AbstractServiceClass(缺省适配器类):它是缺省适配器模式的核心类,使用空方法的形式实现了在ServiceInterface接口中声明的方法。通常将它定义为抽象类,因为对它进行实例化没有任何意义。
  3. ConcreteServiceClass(具体业务类):它是缺省适配器类的子类,在没有引入适配器之前它需要实现适配者接口,因此需要实现在适配者接口中定义的所有方法,而对于一些无须使用的方法不得不提供空实现。在有了缺省适配器之后可以直接继承该适配者类,根据需要有选择性地覆盖在适配器类中定义的方法。

缺省适配器类的典型代码如下:

public abstract class AbstractServiceClass implements ServiceInterface {public void serviceMethod1() {  }  //空方法public void serviceMethod2() {  }  //空方法public void serviceMethod3() {  }  //空方法
}

4 双向适配器

在对象适配器的使用过程中,如果在适配器中同时包含对目标类和适配者类的引用,适配者可以通过它调用目标类中的方法,目标类也可以通过它调用适配者类的方法,那么该适配器就是一个双向适配器。其结构图如下:

其典型代码如下:

public class Adapter implements Target,Adaptee {// 同时维持对抽象目标类和适配者类的引用private Target target;private Adaptee adaptee;public Adapter(Target target) {this.target = target;}public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {adaptee.specificRequest();}public void specificRequest() {target.request();}
}

设计模式之适配器模式详解(附应用举例实现)相关推荐

  1. java connection 单例_Java设计模式之单例模式详解

    Java设计模式之单例模式详解 什么是设计模式 设计模式是在大量的实践中总结和理论之后优选的代码结构,编程风格,以及解决问题的思考方式.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可 ...

  2. 蓝牙:CRC原理详解(附crc16校验代码)

    CRC原理详解(附crc16校验代码) 参考链接: https://www.cnblogs.com/esestt/archive/2007/08/09/848856.html Cyclic Redun ...

  3. 《前端》权限链接--vue前端权限控制方案详解附demo_feiyu_may的博客-CSDN博客_vue 前端权限

    前端权限控制 - 潘正 - 博客园  https://www.cnblogs.com/guchengnan/p/11800947.html vue前端权限控制方案详解附demo_feiyu_may的博 ...

  4. Win+TexLive2020+TexStudio安装过程详解附ElsevierLatex模板下载并使用

    Win+TexLive2020+TexStudio安装过程详解附ElsevierLatex模板下载并使用 一.下载并安装Texlive2020 1.下载TexLive2020 2.安装过程 解压之后运 ...

  5. 计算机排名的985大学排名,2019年985大学名单排名,985大学详解(附全榜单)

    中国最有名的就是211大学和985大学了.2019年211大学名单排名已经为大家公布了,相比之下985大学更加少,全国只有39所985大学,可见985是比211更加有含金量的学校了.下面排行榜123网 ...

  6. .user.ini上传详解附CTF例题

    .user.ini上传详解附CTF例题 题目 解法 https://buuoj.cn/challenges#[SUCTF%202019]CheckIn [SUCTF 2019]CheckIn 题目 解 ...

  7. 数学规划详解(附例题及部分Python实现)

    数学规划详解(附例题及Python实现) 例题来自于清风老师的数学建模课,个人认为讲的非常好,欢迎大家购买 一.概述 1.1 定义 数学规划是运筹学的一个分支,在约束条件下,按照目标函数来寻求计划管理 ...

  8. 设计模式——状态模式详解

    0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦 ...

  9. [SV]SystemVerilog枚举型变量语法详解及应用举例

    SystemVerilog枚举型变量语法详解及应用举例 This section provides the examples to declare SystemVerilog enum of logi ...

最新文章

  1. 组策略(八)使用使用自定义RealVNC adm模板对域内工作站设置统一标准设置
  2. 设计模式理解:中介者模式(Mediator)
  3. Python版——博客网站四 编写日志创建页
  4. 拉屎能赚钱?在马桶上月入过万?原来卫生间里还有这么多隐藏福利,超模君都惊了……
  5. 【bzoj4444】[Scoi2015]国旗计划 倍增
  6. 如何修改ant-input的高度_水质自动采样器的流量计功能如何应用?
  7. 学计算机写作文怎么写,关于学电脑的作文
  8. 暴雪帝国辉煌能否延续
  9. php程序里的configini_PHP: 配置文件 - Manual
  10. PHP生产一个验证码图片,PHP使用GD库生成验证码图片,实现图片验证
  11. linux 限速命令,Linux下网卡限速
  12. 互联网的逻辑和电商的逻辑是不一样的
  13. Linux——Django 开发环境部署(二)python版本控制器pyenv
  14. 「经济理财」 简七理财之小白理财入门篇9堂课
  15. 六、DDE服务器函数
  16. 拓嘉辰丰:拼多多店铺DSR动态评分的更新周期?
  17. Ruby 之Gem kaminari 分页
  18. sublime的安装步骤、sublime的中文设置、sublime连接Linux的sftp(详细)
  19. 如何记账,记录家庭收支情况
  20. mysql我没压岁钱了,你压没压我?岁没岁我?该不该给我压岁钱表情包

热门文章

  1. Go语言的当前状态(2021) | Gopher Daily (2021.02.07) ʕ◔ϖ◔ʔ
  2. redis 什么是冷数据_redis一般存储什么类型数据
  3. opencv库配置常见问题
  4. Linux用户管理命令
  5. 人工智能 遗传算法 计算函数极值问题
  6. ftp连接不上的终极办法 SFTP
  7. 武汉大学武汉校友会测绘分会成立!大势智慧成为会长单位
  8. 2017 年实验班选拔试题
  9. 如何做好一场技术分享
  10. win2012计算机备份,如何使用windows Server2012自带的 Backup备份和恢复