首页 > 代码库 > 如何让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)

如何让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)

如何让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)


概念相关

定义

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

简单点说

两个彼此间没有太大关联的类,想进行交互完成某些事情,如果
直接去修改各自的接口,就显得有些繁琐了,可以加个中间类
用它来协调两类之间的关系,完成相关业务。这种玩法就叫适配器模式!

两种适配器模式

根据适配器类与适配者类的关系不同,适配器模式可分为 类适配器
对象适配器两种,尽管都是三个角色,但还是有些差别的!
另外,类适配器的适配器和适配者是 继承 关系,而对象适
配器则是 引用 关系。

类适配器的三个角色

  • 目标接口(Target):客户所期待的接口,目标是接口
  • 需要适配的类(Adaptee):需要适配的类或适配者类;
  • 适配器(Adapter):实现了抽象目标类接口Target,并继承了适配者类Adaptee

对象适配器的三个角色

  • 目标接口(Target):客户所期待的接口,可以是具体的或抽象的类,也可以是接口
  • 需要适配的类(Adaptee):需要适配的类或适配者类;
  • 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口;

UML类图

技术分享

技术分享


举个最简单栗子

想了很久没想到什么好玩的例子,就写个最简单的英语翻译中文的例子
了解这个模式的玩法,后面有好的例子再换。


对象适配器的写法(用得较多)

说中文的接口:

技术分享

说英语的人:

技术分享

适配翻译器:

技术分享

英语翻译成中文:

技术分享

翻译后:

技术分享

好的,非常简单,在适配类中传入需要转换的对象,完成转换而已。


类适配模式写法

技术分享

翻译过程:

技术分享

翻译结果:

技术分享


两种玩法对比

对象适配器支持传入一个被适配器对象,因此可以做到对多种被适
配接口进行适配。而类适配器直接继承,无法动态修改,所以一般情况
下对象适配器使用得更多!(Java不支持多重继承!!!)


缺省适配器模式

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

简单点说就是:不想实现接口里的所有方法,写个基类去继承这个
接口,然后重写所有方法,子类再去继承这个基类,按需重写!

比如上面的例子,中文也有很多种类型啊,普通话,广东话,上海话:
我们现在只需要转换成普通话:

技术分享

写个父类适配器:

技术分享

写个普通话转换用的适配器:

技术分享

开始翻译:

技术分享

翻译结果:

技术分享


小结


优点

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的
    适配者类,无须修改原有结构。
  • 增加了类的透明性和复用性,将具体的业务实现过程封装在适配
    者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,
    同一个适配者类可以在多个不同的系统中复用。
  • 灵活性和扩展性都非常好,可以很方便地更换适配器。
  • 一个对象适配器可以把多个不同的适配者适配到同一个目标。

缺点

  • 类适配器模式对于不支持多重类继承的语言,一次最多只能适配
    一个适配者类,不能同时适配多个适配者。
  • 适配者类不能为最终类,如在Java中不能为final类。
  • 在Java中,类适配器模式中的目标抽象类只能为接口,不能为类,
    其使用有一定的局限性。
  • 对象适配器要在适配器中置换适配者类的某些方法比较麻烦。

摘自工匠若水的——设计模式(结构型)之适配器模式(Adapter Pattern)


本节代码

https://github.com/coder-pig/DesignPatternsExample/tree/master/6.Adapter%20Pattern


<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    如何让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)