定义

  适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式的用途

  用电器做例子,笔记本电脑的插头一般都是三相的,即除了阳极、阴极外,还有一个地极。而有些地方的电源插座却只有两极,没有地极。电源插座与笔记本电脑的电源插头不匹配使得笔记本电脑无法使用。这时候一个三相到两相的转换器(适配器)就能解决此问题,而这正像是本模式所做的事情。

适配器模式的结构

  适配器模式有类的适配器模式对象的适配器模式两种不同的形式。

  a.类适配器模式

  类的适配器模式把适配的类的API转换成为目标类的API。

  在上图中可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,提供一个中间环节,即类Adapter,把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是继承关系,这决定了这个适配器模式是类的:

  模式所涉及的角色有:

  ●  目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

  ●  源(Adapee)角色:现在需要适配的接口。

  ●  适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

源码:

public interface Target {/*** 这是源类Adaptee也有的方法*/public void sampleOperation1(); /*** 这是源类Adapteee没有的方法*/public void sampleOperation2();
}/*
*上面给出的是目标角色的源代码,这个角色是以一个JAVA接口的形式实现的。可以看出,这个接口声明了两个方法:*sampleOperation1()和sampleOperation2()。而源角色Adaptee是一个具体类,它有一个sampleOperation1()方法,但是没有sampleOperation2()方法。
*/public class Adaptee {public void sampleOperation1(){}}/*
*适配器角色Adapter扩展了Adaptee,同时又实现了目标(Target)接口。由于Adaptee没有提供sampleOperation2()方法,*而目标接口又要求这个方法,因此适配器角色Adapter实现了这个方法。
*/public class Adapter extends Adaptee implements Target {/*** 由于源类Adaptee没有方法sampleOperation2()* 因此适配器补充上这个方法*/@Overridepublic void sampleOperation2() {//写相关的代码
    }
}

 b.对象适配器模式

与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。

  从上图可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

源码:

public interface Target {/*** 这是源类Adaptee也有的方法*/public void sampleOperation1(); /*** 这是源类Adapteee没有的方法*/public void sampleOperation2();
}public class Adaptee {public void sampleOperation1(){}}public class Adapter {private Adaptee adaptee;public Adapter(Adaptee adaptee){this.adaptee = adaptee;}/*** 源类Adaptee有方法sampleOperation1* 因此适配器类直接委派即可*/public void sampleOperation1(){this.adaptee.sampleOperation1();}/*** 源类Adaptee没有方法sampleOperation2* 因此由适配器类需要补充此方法*/public void sampleOperation2(){//写相关的代码
    }
}

类适配器和对象适配器的权衡

  ●  类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。

  ●  对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和Adaptee的子类一起工作,因为继承是静态的关系,当适配器继承了Adaptee后,就不可能再去处理  Adaptee的子类了。

     对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。

  ●   对于类适配器,适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法。

     对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然重定义Adaptee的行为比较困难,但是想要增加一些新的行为则方便的很,而且新增加的行为可同时适用于所有的源。

  ●  对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee。

     对于对象适配器,需要额外的引用来间接得到Adaptee。

  建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。

适配器模式的优点

  •   更好的复用性

  系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。

  •   更好的扩展性

  在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。

适配器模式的缺点

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

缺省适配模式

  缺省适配(Default Adapter)模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。作为适配器模式的一个特例,缺省是适配模式在JAVA语言中有着特殊的应用。

源码示例:

/**
*鲁智深的故事
*  和尚要做什么呢?吃斋、念经、打坐、撞钟、习武等。如果设计一个和尚*接口,*给出所有的和尚都需要实现的方法,那么这个接口应当如下:
*/public interface 和尚 {public void 吃斋();public void 念经();public void 打坐();public void 撞钟();public void 习武();public String getName();
}/*
*显然,所有的和尚类都应当实现接口所定义的全部方法,不然就根本通不过JAVA语言编辑器。像下面的鲁智深类就不行。
*/public class 鲁智深 implements 和尚{public void 习武(){拳打镇关西;大闹五台山;大闹桃花村;火烧瓦官寺;倒拔垂杨柳;}public String getName(){return "鲁智深";}
}/**
*  由于鲁智深只实现了getName()和习武()方法,而没有实现任何其他的方法。因此,它根本就通不过Java语言编译器。*鲁智深类只有实现和尚接口的所有的方法才可以通过Java语言编译器,但是这样一来鲁智深就不再是鲁智深了。*以史为鉴,可以知天下。研究一下几百年前鲁智深是怎么剃度成和尚的,会对Java编程有很大的启发。*不错,当初鲁达剃度,众僧说:“此人形容丑恶、相貌凶顽,不可剃度他",但是长老却说:*”此人上应天星、心地刚直。虽然时下凶顽,命中驳杂,久后却得清净。证果非凡,汝等皆不及他。”
*原来如此!看来只要这里也应上一个天星的话,问题就解决了!使用面向对象的语言来说,“应”者,实现也;“天星”者,抽象类也。
*/public abstract class 天星 implements 和尚 {public void 吃斋(){}public void 念经(){}public void 打坐(){}public void 撞钟(){}public void 习武(){}public String getName(){return null;}
}/*
*鲁智深类继承抽象类“天星”
*/public class 鲁智深 extends 和尚{public void 习武(){拳打镇关西;大闹五台山;大闹桃花村;火烧瓦官寺;倒拔垂杨柳;}public String getName(){return "鲁智深";}
}

这个抽象的天星类便是一个适配器类,鲁智深实际上借助于适配器模式达到了剃度的目的。此适配器类实现了和尚接口所要求的所有方法。但是与通常的适配器模式不同的是,此适配器类给出的所有的方法的实现都是“平庸”的。这种“平庸化”的适配器模式称作缺省适配模式。

  在很多情况下,必须让一个具体类实现某一个接口,但是这个类又用不到接口所规定的所有的方法。通常的处理方法是,这个具体类要实现所有的方法,那些有用的方法要有实现,那些没有用的方法也要有空的、平庸的实现。

  这些空的方法是一种浪费,有时也是一种混乱。除非看过这些空方法的代码,程序员可能会以为这些方法不是空的。即便他知道其中有一些方法是空的,也不一定知道哪些方法是空的,哪些方法不是空的,除非看过这些方法的源代码或是文档。

  缺省适配模式可以很好的处理这一情况。可以设计一个抽象的适配器类实现接口,此抽象类要给接口所要求的每一种方法都提供一个空的方法。就像帮助了鲁智深的“上应天星”一样,此抽象类可以使它的具体子类免于被迫实现空的方法。

缺省适配模式的结构

  缺省适配模式是一种“平庸”化的适配器模式。

  

源码:

public interface AbstractService {public void serviceOperation1();public int serviceOperation2();public String serviceOperation3();
}public abstract class ServiceAdapter implements AbstractService{@Overridepublic void serviceOperation1() {}@Overridepublic int serviceOperation2() {return 0;}@Overridepublic String serviceOperation3() {return null;}
}

可以看到,接口AbstractService要求定义三个方法,分别是serviceOperation1()、serviceOperation2()、serviceOperation3();而抽象适配器类ServiceAdapter则为这三种方法都提供了平庸的实现。因此,任何继承自抽象类ServiceAdapter的具体类都可以选择它所需要的方法实现,而不必理会其他的不需要的方法。

  适配器模式的用意是要改变源的接口,以便于目标接口相容。缺省适配的用意稍有不同,它是为了方便建立一个不平庸的适配器类而提供的一种平庸实现。

  在任何时候,如果不准备实现一个接口的所有方法时,就可以使用“缺省适配模式”制造一个抽象类,给出所有方法的平庸的具体实现。这样,从这个抽象类再继承下去的子类就不必实现所有的方法了。

参考:http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html

转载于:https://www.cnblogs.com/KongkOngL/p/6864389.html

Java设计模式の适配器模式相关推荐

  1. Java | 设计模式-适配器模式

    继代理模式后又来到适配器模式啦,想看之前的也有哦.持续更新中哦.让我们一起加油吧兄弟们,干他. 很喜欢一句话:"八小时内谋生活,八小时外谋发展". 你好,如果喜欢,请一起坚持!! ...

  2. java设计模式适配器模式_Java中的适配器设计模式

    java设计模式适配器模式 适配器设计模式是一种结构设计模式 ,可以帮助我们连接到通过不同接口公开相似功能的旧版或第三方代码. 适配器的现实世界是我们用来将USB电缆连接到以太网端口的类比. 在设计一 ...

  3. java设计模式适配器模式_Java解释器设计模式

    java设计模式适配器模式 Interpreter design pattern is one of the behavioral design pattern. Interpreter patter ...

  4. 【设计模式】Java设计模式 - 适配器模式

    [设计模式]Java设计模式 - 适配器模式

  5. JAVA设计模式--适配器模式

    目录 1.什么是适配器模式 2.适配器模式的适用场景 3.适配器模式的结构 4.适配器模式应用举例 5.适配器模式的选择 参考文章 1.什么是适配器模式 适配器(Adapter)模式又叫做包装( Wr ...

  6. Java设计模式——适配器模式【Adapter Pattern】

    一.引言 23种设计模式大概分为三大类: 5种(创建型模式):工厂方法模式.抽象工厂模式.单例模式.原型模式.建造者模式. 7种(结构型模式):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...

  7. java设计模式-适配器模式

    模式导读:    每个人都有自己不同的需要,每个人都有自己能够接受的不同方式,就像是为满足现在快速度发展的社会,几乎人人离不开手机的时代,我们也许会碰到在外出行手机电量不足的情况,这个时候如果你在车站 ...

  8. java设计模式---适配器模式

    类适配器 客户的开发人员定义了一个接口,期望用这个接口来完成整数的求和操作,接口定义如下: Java代码   public interface Operation{         public in ...

  9. Java设计模式 - 适配器模式

    概述 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 构造器模式 上面的概述可能不是太容易理解,下面举一个例子说明适配器模式的应用. ...

  10. Java设计模式-适配器模式Adapter

    定义:"转换接口" 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 我理解的"一个类的接口&q ...

最新文章

  1. 2021年Java面试题目最新总结【90%面试会踩的坑】
  2. 通过SolrJ 4.9管理Solr core
  3. 《道德经》程序员版第五章
  4. 高德地图联手中国气象局,积水地图 AI 版实时预测道路积水
  5. C#分布式缓存二:Asp.Net中使用Couchbase
  6. 高通发布《5G经济》研究:将催生12万亿美元市场
  7. kml文件转成cvs_KMZ KML与SHP文件互相转换
  8. 计算机函数公式发生额总计,16个Excel函数公式,解决会计工作中80﹪的难题!
  9. 旧手机利用(Android),当wifi,当mic,当ipcamera
  10. 英雄联盟android,安卓ARPG佳作 《英雄联盟(League of Heroes)》
  11. 消失的遗传力--wiki
  12. 华为“More Bits, Less Watts”新践行
  13. 导出文件(图片、图片集)
  14. html如何将地址、路径、支付code_url转成二维码
  15. 音频信号转为开关控制信号_盘点模拟量信号和开关量信号区别与应用
  16. 个人开发者App Store收款
  17. 发现电脑屏幕总是不自动关闭?看看你是否打开了这些程序……
  18. 21世纪25大扣将排行榜(组图)
  19. Automatic Targetless Extrinsic Calibration of Multiple 3D LiDARs and Radars
  20. CBN(Cross-Iteration Batch Normalization)论文详解

热门文章

  1. 中国 X86 服务器市场 10 年来首次负增长
  2. Android之Retrofit详解(转载)
  3. 自动触发click事件
  4. 网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon)
  5. 001 lambda的分析
  6. 自动化测试 短信验证登录
  7. 微信对网络影响的技术试验及分析(论文全文)
  8. 关于Eclipse的常用快捷键
  9. MySQL 中的日期时间类型
  10. oracle第三天笔记