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. CentOS 6.4 64位 安装 mysql 5.6.24

    下载安装包 由于官网访问及版本选择下载不太方便,使用 suho 的源进行下载 http://mirrors.sohu.com/mysql/MySQL-5.6/ 下载如下三个安装包: MySQL-ser ...

  2. SQL70001: This statement is not recognized in this context.

    关于错误: SQL70001: This statement is not recognized in this context. 的产生原因以及解决办法.   在SQL Server Databas ...

  3. div section article aside的理解

    div 是一个大的容器 内部可以包含header main nav aside footer等标签 没有语义,多用于为脚本添加样式 section的语义比div语义强些,用于主题性比较强的内容,比如一 ...

  4. python读取excel文件

    一.xlrd的说明 xlrd是专门用来在python中读取excel文档的模块,使用前需要安装. 可以到这https://pypi.python.org/pypi/xlrd进行下载tar.gz文件,然 ...

  5. C语言-06数据类型-05 总结

    一.基本数据类型1.int1> long int.long:8个字节 %ld2> short int.short:2个字节 %d %i3> unsigned int.unsigned ...

  6. Scut 上线后遇到的问题

    1. 上线后的大并发问题: var sem = new Semaphore(_accepts, _accepts); while (true) { sem.WaitOne(); #pragma war ...

  7. C#使用字符串分割字符串

    我们都会用字符分割字符串: string[] recvArr = recv.Split(';'); 如果用字符串分割呢?下面: string[] sArray = Regex.Split(recv, ...

  8. C#委托(Delegate)学习日记

    在.NET平台下,委托类型用来定义和响应应用程序中的回调.事实上,.NET委托类型是一个类型安全的对象,指向可以以后调用的其他方法.和传统的C++函数指针不同,.NET委托是内置支持多路广播和异步方法 ...

  9. C#入门教程笔记

    1.C# string api Substring(),//截取字符串,接受两个参数,第一个是偏移量,第二个是截取长度 replace(),//替换字符串,接受两个参数,第一个指定被替换的字符串,第二 ...

  10. FTP原理和cent OS vsFTPd架设

    1.ftp为明码传输 2.客户端和服务端采用两条链路来分别进行命令和数据的传输.数据传输的模式分为主动链接和被动链接. 3.客户端在需要数据的时候,会告知服务器端采取主动或者被动的方式来链接. 4.如 ...