定义

将类的接口转化为客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作,别名Wrapper(包装器)。

适配器模式,最终改变一个已有对象的接口。

使用场景

当有那么个类,那么个对象,却不是我想要的接口类型,肿么办?不要方,用适配器模式。

java三要素:Target(目标)+Adaptee(待适配者)+Adapter(适配器)

  • 类的适配器,实现Target接口,继承Adaptee类,把待适配类的API转化为目标接口的API。
  • 对象适配器,实现Target接口,持有Adaptee对象,把待适配类的API转化为目标接口的API。
  • 缺省适配器,abstract适配器(Adapter)实现Target接口,任意实现Adapter抽象类的均是Target接口类型,而不用实现全部Target接口方法。

个人理解

好比一个多用插排,将各种插头(Adaptee)通过插排(Adapter)适配到标准插口(Target)。

代码示例

interface Target {
void targetMethod1();
void targetMethod2();
} class Adaptee {
public void targetMethod1() {
}
}

//类的适配器(继承,涉及类之间的关系,所以是类的适配器)
//java中没有多继承,使用单继承+实现接口,解决问题
class Adapter extends Adaptee implements Target {
@Override
public void targetMethod2() {
}
} class Test{
public static void main(String[] args) {
Target target=new Adapter();//适配器Adapter将Adaptee类型适配成了Target目标接口类型
target.targetMethod1();
target.targetMethod2();
}
}


//对象适配器(类似一个包装类,将待适配类和目标类的API衔接,其中Adapter和Adaptee是委托关系,所以是对象的适配器)
//java中较为常见,注入待适配对象(Adaptee),实现目标接口即可。
class Adapter implements Target{
Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee=adaptee;
}
@Override
public void targetMethod1() {
adaptee.targetMethod1();
}
@Override
public void targetMethod2() {
}
} class Test{
public static void main(String[] args) {
Target target=new Adapter(new Adaptee());
target.targetMethod1();
target.targetMethod2();
}
}

//缺省适配器,任意Adapter实现类均是Target接口类型,而不行实现Target全部定义方法
//缺省适配的用意是为了方便建立一个不平庸的适配器类而提供的一种“平庸”实现,使得具体实现类免于被迫实现空的方法。
abstract class Adapter implements Target{
public void targetMethod1(){}//平庸化的实现,可空,可return null;
public void targetMethod2(){}
}
class Client1 extends Adapter{
@Override
public void targetMethod1(){
}
}
class Client2 extends Adapter{
@Override
public void targetMethod2(){
}
}
class Test{
public static void main(String[] args) {
new Client1().targetMethod1();
new Client2().targetMethod1();
}
}

类适配器和对象适配器

  1. 类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
  2. 类适配器可以重新定义Adaptee的部分行为,对象适配器适合新增新的行为。
  3. 类的适配器不需要额外引用得到Adaptee。

优缺点

  • 优点

    1. 复用现存代码,应用于新接口
    2. 将Target和Adaptee解耦
    3. 一个适配器,可以同时对多个Adaptee适配成Target
    4. 适配时可以组合自定义功能,扩展性良好(类似装饰)
  • 缺点
    1. 过多的依赖适配器,会导致对适配器修改较复杂
    2. 过多的适配器,会使得系统凌乱不清晰,如非必要,可以不使用

JDK中的适配器模式

如:java.util.Arrays

    //将本身适配成list接口
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

相关模式

装饰模式增加了对象的功能,但是不改变对象的接口,透明性较好,并且支持递归组合,是适配器模式虽然也为对象增加了功能,但是改变了接口,不支持递归组合。

代理模式,也是不改变接口的前提下,为一个对象的访问,提供了一个代理,使用场景不同。

参考这里

参考这里

适配器模式/adapter模式/结构型模式的更多相关文章

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

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

  2. 代理模式/proxy模式/结构型模式

    代理模式proxy 定义 为其他对象提供一种代理,并以控制对这个对象的访问.最简单的理解,买东西都是要去商店的,不会去工厂. java实现三要素 proxy(代理)+subject(接口)+realS ...

  3. 设计模式(十二): Flyweight享元模式 -- 结构型模式

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  4. 设计模式(十三): Proxy代理模式 -- 结构型模式

      设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路 ...

  5. 设计模式(十一):FACADE外观模式 -- 结构型模式

    1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇 ...

  6. 设计模式学习之路——Facade 外观模式(结构型模式)

    动机: 组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战.如何简化外部客户程序和系统间的交互接口?如何将外部客户程序的演化和内部子系 ...

  7. 设计模式(十):Decorator装饰者模式 -- 结构型模式

    1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继 ...

  8. 设计模式(八):Bridge桥接模式 -- 结构型模式

    1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...

  9. 设计模式学习之适配器模式(Adapter,结构型模式)(14)

    参考链接:http://www.cnblogs.com/zhili/p/AdapterPattern.html一.定义:将一个类的接口转换成客户希望的另一个接口.Adapter模式使得原本由于接口不兼 ...

随机推荐

  1. c# WebClient文件下载

    public void HttpDownload(string url, string path, ResourceType type) { using (var client = new WebCl ...

  2. Webpack--自学笔记

    原文--http://webpack.github.io/docs/tutorials/getting-started/ 什么是webpack? webpack是一个模块打包器.webpack把模块( ...

  3. FragmentPagerAdapter+ViewPager+Fragment

    FragmentPagerAdapter中会在滑动到2页时,会预加载第三个页面.如果在这些页面中都有网络请求,那么当你还没有看到第三页时,第三页的数据请求已经发出.这样就会造成,当已进入该页面,可能会 ...

  4. jquery实现简单瀑布流布局(续):图片懒加载

    # jquery实现简单瀑布流布局(续):图片懒加载 这篇文章是jquery实现简单瀑布流布局思想的小小扩展.代码基于前作的代码继续完善. 图片懒加载就是符合某些条件时才触发图片的加载.最常见的具体表 ...

  5. JS 原型的妙用

    原型是JS的一个重要的特征,通过它可以实现类和实例直接的继承关系. 1.原型来来实现数据备份 // 通过原型来来实现数据备份 function p(x){ this.x = x; } p.protot ...

  6. strace追踪未开始或者来不及捕获pid的进程(译)

    我的个人博客网站最近被攻击了,被用来发送一些垃圾邮件.但是我不知道这个进程是怎么来的,用top查看发现一个不知道干什么的perl脚本,决定给用strace查看一下. strace可以追踪一个进程的系统 ...

  7. C#深入浅出 继承(六)

    这个标题写出来好长时间了,都没写内容,今天无论如何都得写完它,昨天写了一段,尼玛,电脑突然死机,重启之后啥都没了. 继承嘛,有人觉得很简单,但是里面还是有内容可以讲的,因为面向对象也就这么点内容,封装 ...

  8. 获取PHP文件绝对地址$_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 的区别

    通常情况下,PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 都会返回 PHP 文件的完整路径(绝对路径)与文件名: <?php echo 'SCRIPT_F ...

  9. ReactiveCocoa源码拆分解析(三)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 这一章节主要讨论信号的“冷”与“热” 在RAC的世界 ...

  10. 前端XSS攻击和防御

    xss跨站脚本攻击(Cross Site Scripting),是一种经常出现在web应用中的计算机安全漏洞,指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会 ...