1、模式简介

适配器模式解决的问题:

  让原本因为接口不兼容而不能一起工作的类可以一起工作。

适配器模式的UML原理图如下图所示:

  从上图可见,客户想要用Target接口实现Adaptee接口中的方法,但这显然是不可能的。因此,我们需要定义一个适配器类Adapter,让它在Target和Adaptee之间做一个“调停者”,进而达到Target和Adaptee的适配。

适配器模式中有三种角色:

  • 目标接口Target:用户期望使用的接口,这个类可以是接口,也可以是抽象类或具体类;
  • 需要适配的类Adaptee:当前系统中有的类;
  • 适配器Adapter:在现有接口和目标接口之间的“调停者”,作用是将现有接口转换成目标接口。

适配器模式的优点:

  • 通过适配器模式,用户在做相似的操作时可以调用同一个接口,其内部过程对于用户是透明的,这样做更简单、更直接、更解耦;
  • 复用了现存的类,解决了现存类和复用环境要求不一致的问题;
  • 将目标接口和现有接口解耦,通过引入一个适配器类,而无需修改原有的代码。

适配器模式的缺点:

  使用适配器模式后,如果想要改变适配对象,就需要更换适配器,而更换适配器是一个非常复杂的过程。

适配器模式的适用场景:

  • 当系统需要使用现有的类,而现有的类不符合系统的接口的时候;
  • 当期望的功能和系统中现有的某个类的功能相似,但是具有不同的接口的时候;
  • 当系统已经实现了某个功能,但用户想要通过另一种接口方式访问,而我们不想修改原有接口的时候;
  • 当使用的第三方组件的接口和系统中定义好的接口不同,但又不希望修改系统接口的时候。

2、代码

  适配器模式有两种实现形式:类适配模式和对象适配模式。下面通过一个实例分别介绍这两种模式。

需求:

  我们现在的系统中有一个现有的类Adaptee,这个类中有一个adapteeMethod()方法。但是用户不想用Adaptee这个累,他们想用一个他们自己提供的接口Target,这个接口中有一个targetMethod()方法。虽然这两个类的功能相同,但是Target毕竟是一个接口,我们无法直接调用Adaptee类中的方法,而且我们也不想再把我们千辛万苦写好的Adaptee类中的代码重新写一遍。我们该怎么办?

  在解决上面的问题之前,我们先给出Adaptee和Target中的代码:

  Adaptee类中的代码:

public class Adaptee {
public void adapteeMethod() {
System.out.println("这是我们已经实现的功能!");
}
}

  Target接口中的代码:

public interface Target {
void targetMethod();
}

  接下来,我们分别用类适配模式和对象适配模式定义Adapter适配器类,来解决上面的问题。

2.1、类适配模式

  首先来看类适配模式的UML图:

  可以看到,类适配模式是将Adapter类直接继承Adaptee,这样就直接具有了Adaptee中的adapteeMethod()方法,然后直接在Adapter中实现的Target的targetMethod()方法中调用父类的方法即可达到适配效果。

  Adapter类中的代码如下:

public class Adapter extends Adaptee implements Target {

      @Override
public void targetMethod() {
super.adapteeMethod();
}
}

  测试代码如下:

public class Test {
public static void main(String[] args) {
Targettarget = new Adapter();
target.targetMethod();
}
}

  运行结果如下图所示:

2.2、对象适配模式

  同理,先来看对象适配模式的UML图:

  可以看到,Adapter不再继承Adaptee,而是持有一个Adaptee类的引用,即将一个Adaptee的对象引用到Adapter类中,这就是对象适配模式的思路。同样,在Adapter的targetMethod()方法中调用Adaptee对象的adapteeMethod()方法即可完成适配。

  Adapter类中的代码如下:

public class Adapter implements Target {
private Adaptee adaptee = new Adaptee(); @Override
public void targetMethod() {
adaptee.adapteeMethod();
}
}

  测试代码与类适配模式的测试代码完全相同。运行结果如下图所示:

以上就是对适配器模式AdapterPattern的介绍。

最后贴出适配器模式的GitHub代码:【GitHub - Adapter】

【设计模式 - 5】之适配器模式(Adapter)的更多相关文章

  1. 设计模式 结构型 - 适配器模式 Adapter

    Adapter(适配器模式) ---- 加个“适配器”以便于复用 将一个类的接口转换成客户希望的另一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 应用场景 如果 ...

  2. 设计模式系列之适配器模式(Adapter Pattern)——不兼容结构的协调

    模式概述 模式定义 模式结构图 模式伪代码 类适配器,双向适配器,缺省适配器 类适配器 双向适配器 缺省适配器 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 主要缺点 适 ...

  3. IOS设计模式浅析之适配器模式(Adapter)

    引言 在项目开发中,有时候会遇到这样的一种情景:需要使用以前开发的“一些现存的对象”,但是新环境中要求的接口是这些现存对象所不满足的.怎样应对这种迁移的需求?使得可以复用这些对象,以满足新的应用环境, ...

  4. 《JAVA设计模式》之适配器模式(Adapter)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述适配器(Adapter)模式的: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能 ...

  5. 设计模式(五)适配器模式Adapter(结构型)

      设计模式(五)适配器模式Adapter(结构型) 1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相 ...

  6. 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)

    原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...

  7. 8.3 GOF设计模式二: 适配器模式 Adapter

    GOF设计模式二: 适配器模式 Adapter  为中国市场生产的电器,到了美国,需要有一个转接器才能使用墙上的插座,这个转接 器的功能.原理?复习单实例模式  SingleTon的三个关键点  ...

  8. 怎样让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)

    怎样让孩子爱上设计模式 -- 7.适配器模式(Adapter Pattern) 标签: 设计模式初涉 概念相关 定义: 适配器模式把一个类的接口变换成client所期待的还有一种接口,从而 使原本因接 ...

  9. 二十四种设计模式:适配器模式(Adapter Pattern)

    适配器模式(Adapter Pattern) 介绍将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.示例有一个Message实体类 ...

  10. 设计模式 - 适配器模式(adapter pattern) 具体解释

    适配器模式(adapter pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 适配器模式(adapter pattern): 将一个类的接 ...

随机推荐

  1. Nodejs简单验证码ccap安装

    首先要求: node npm 安装时如果提示npm-gyp失败,可进行如下操作: 确认python版本2.7+ 安装npm install ccap 如果失败,尝试npm install ccap@0 ...

  2. Eyeshot Ultimate 学习笔记(1)

    在Winform项目中用到3D技术,这是在做项目一段时间以来第一次,还是指定的3D控件Eyeshot Ultimate,这个控件名称用度娘搜索,竟然毫无结果,不知道是没有人用过还是觉得该控件过于简单, ...

  3. ListView的setOnItemClickListener和setOnItemLongClickListener同时响应的问题

    lvContentList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(A ...

  4. 为何要fork()两次来避免产生僵尸进程??

    最近安装书上说的,开始搞多进程了..看到了一个好帖子,学习学习 http://blog.sina.com.cn/s/blog_9f1496990100y420.html 首先我们要明白,为什么要避免僵 ...

  5. codevs 1557 热浪

    传送门 题目描述 Description 德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品.Farmer John此时以先天 ...

  6. Spring4.0整合Hibernate3 .6

    转载自:http://greatwqs.iteye.com/blog/1044271 6.5  Spring整合Hibernate 时至今日,可能极少有J2EE应用会直接以JDBC方式进行持久层访问. ...

  7. bzoj 2631: tree 动态树+常数优化

    2631: tree Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1716  Solved: 576[Submit][Status] Descrip ...

  8. 如何搭建一个独立博客——简明Github Pages与Hexo教程

    摘要:这是一篇很详尽的独立博客搭建教程,里面介绍了域名注册.DNS设置.github和Hexo设置等过程,这是我写得最长的一篇教程.我想将我搭建独立博客的过程在一篇文章中尽可能详细地写出来,希望能给后 ...

  9. MVC自学系列之四(MVC模型-Models)

    ASP.NET MVC 提供了一系列工具和特性去使用仅仅定义的对象模型.你可以坐下来好好思考你将要解决的问题,并且写好C#类,当你准备好时就可以使用MVC提供的工具去为每一个实体构建标准的index. ...

  10. 在前台运行Service

    一个前台的 service是被用户强烈关注的从而不会在内存低时被系统杀死.前台 service必须在状态栏上提供一个通知,这个通知被放在"正在进行"区域中,这表示这个通知不能被解除,除非服务停止了或者 ...