神头鬼脸之适配器模式

今天是设计模式学习系列的第7篇–适配器模式

开头三问?

  1. 什么是适配器模式?什么是类的适配器模式、对象的适配器模式、接口的适配器模式?
  2. 适配器模式和装饰者模式的区别?
  3. 适配器模式的使用场景?

带着这几个问题,开始我们今天的学习吧。

适配器模式解析

说到适配器模式,其实顾名思义不难理解,我举一个例子。

相信很多朋友都有去过香港买东西,比如我曾经去香港买了一个 ipad air,但是呢,港版的它的充电器插头和我们大陆的插座是不适配的。

神头鬼脸之适配器模式_第1张图片

但是我已经买回来了,这个插头可是不能直接充电的,那怎么办呢?这时候我去淘宝上买了一个转换器。

神头鬼脸之适配器模式_第2张图片

这样一来就可以愉快的使用了,那么上面这个例子中,适配器的作用就是位于港版插头和我们大陆插座之间,它的工作将大陆插座转换成港版插座,好让港版插头可以插入得到电力。其实 适配器模式和真实世界的 适配器 扮演着同样的角色:将一个接口转换成另一个接口,以符合客户的期望。

我们使用适配器模式的过程一般如下:

  1. 通过目标接口调用适配器的方法对适配器发出请求;
  2. 适配器使用被适配者接口把请求转换成被适配者的一个或多个接口;
  3. 客户接收到调用结果,但是感知不到适配器在起转换作用;

结合上面的例子,港版充电头就是客户,它要调用港版标准插座进行充电,而淘宝买的转换器就是适配器,它实现了一个目标接口(提供港版插座接口),被适配者就是我们的大陆插座接口; 需要注意的是,客户和被适配者是解耦的,一个不知道另一个。

定义适配器模式:

将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

类图如下:

神头鬼脸之适配器模式_第3张图片

适配器模式充满着良好的 OO 设计原则: 使用对象组合,提供修改的接口包装被适配者,这种做法还有额外的优点就是 被适配者的任何子类都可以搭配适配器使用

核心思想就是有一个 Adaptee 类,拥有一个方法待适配,目标接口是 Target ,通过 Adapter 类将 Adaptee 的功能扩展到 Target 里。

下面来看段代码加深理解:

/**被适配者*/
public class Adaptee {
     
    public void method1() {
     
        System.out.println("this is original method!");
    }
}
/**目标接口*/
public interface Target {
     
    /**
     * 与原类中的方法相同
     */
    public void method1();
    /**
     * 新类的方法
     */
    public void method2();
}
/**Adapter 实现 Target 接口,组合了Adaptee*/
public class Adapter implements Target {
     
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
     
        super();
        this.adaptee = adaptee;
    }

    @Override
    public void method2() {
     
        System.out.println("this is the target method!");
    }

    @Override
    public void method1() {
     
        adaptee.method1();
    }
}
/**测试类*/
public class AdapterTest {
     
    public static void main(String[] args) {
     
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.method1();
        target.method2();
    }
}

上面我们已经定义了适配器模式,不过实际上适配器模式分为 “对象适配器” 、 “类适配器”和“接口”适配器。

上面我们画的类图是 对象适配器的,接下来一起看看什么是类适配器和接口适配器。

类适配器

神头鬼脸之适配器模式_第4张图片

区别就在于 Adapter 类继承 Adaptee 类,实现 Target 接口:

/**
 * 类适配器
 */
public class Adapter extends Adaptee implements Target {
    @Override
    public void method2() {
        System.out.println("this is the target method!");
    }
}

接口适配器

第三种适配器模式是接口的适配器模式,接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。看一下类图:

神头鬼脸之适配器模式_第5张图片

这个很好理解,在实际开发中,我们也常会遇到这种接口中定义了太多的方法,以致于有时我们在一些实现类中并不是都需要。

适配器和装饰者模式的区别?

学了适配器模式你可能会感觉和装饰者模式非常像,都是持有一个对象实例,然后进行功能组装。

不过两者的侧重点吗是不同的: 适配器是将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而下一篇我准备写的外观模式是将一群对象 “包装” 起来以简化其接口,敬请期待。

这里还要注意: 装饰者不改变接口,只是加入责任,而适配器是将一个接口转成另一个接口;

适配者的使用场景

当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器。比如早起的JDK中集合类型的迭代器是 Enumeration 枚举。但是 后来新的 JDK 使用的是 Iterator,当我们对面遗留代码,这些代码暴露出枚举接口,但我们又希望在新的代码中只使用迭代器,解决这个问题我们就可以构造一个适配器,持有枚举 Enumeration 类的实例,即被适配者即可。

好了,适配器模式我们就学到这里。概念很好理解,希望大家定期按照本文开头一样,定期问自己这几个问题,不然这个东西非常容易忘记,当大脑梳理清楚后,在工作中写代码时多结合使用,相信你的代码会越写越顺滑。


全文完,fighting!

你可能感兴趣的:(设计模式,适配器模式,设计模式,java,编程语言,抽象类)