Java设计模式(七)适配器模式

Author Avatar
wshunli 9月 10, 2018
  • 在其它设备中阅读本文章

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

适配器模式

适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。

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

类适配器模式

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

适配器模式

在上图中可以看出,Adaptee 类并没有 sampleOperation2() 方法,而客户端则期待这个方法。

为使客户端能够使用 Adaptee 类,提供一个中间环节,即类 Adapter ,把 Adaptee 的 API 与 Target 类的 API 衔接起来。Adapter 与 Adaptee 是继承关系,这决定了这个适配器模式是类的。

模式所涉及的角色有:

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

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

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

1、目标角色

public interface Target {
    /**
     * 这是源类Adaptee也有的方法
     */
    public void sampleOperation1();
    /**
     * 这是源类Adapteee没有的方法
     */
    public void sampleOperation2();
}

2、源角色

public class Adaptee {
    public void sampleOperation1() {
        System.out.println("Adaptee.sampleOperation1()");
    }
}

3、适配器角色 ClassAdapter 扩展了 Adaptee ,同时又实现了目标(Target)接口。

public class ClassAdapter extends Adaptee implements Target {
    /**
     * 由于源类Adaptee没有方法sampleOperation2()
     * 因此适配器补充上这个方法
     */
    @Override
    public void sampleOperation2() {
        System.out.println("ClassAdapter.sampleOperation2()");
    }
}

对象适配器模式

与类的适配器模式一样,对象的适配器模式把被适配的类的 API 转换成为目标类的 API。

与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到 Adaptee 类,而是使用委派关系连接到 Adaptee 类。

适配器模式

在上图中可以看出,Adaptee 类并没有 sampleOperation2() 方法,而客户端则期待这个方法。

为使客户端能够使用 Adaptee 类,需要提供一个包装(Wrapper)类 Adapter。这个包装类包装了一个 Adaptee 的实例,从而此包装类能够把Adaptee 的 API 与 Target 类的 API 衔接起来。Adapter 与 Adaptee 是委派关系,这决定了适配器模式是对象的。

1、目标角色

public interface Target {
    /**
     * 这是源类Adaptee也有的方法
     */
    public void sampleOperation1();
    /**
     * 这是源类Adapteee没有的方法
     */
    public void sampleOperation2();
}

2、源角色

public class Adaptee {
    public void sampleOperation1() {
        System.out.println("Adaptee.sampleOperation1()");
    }
}

3、适配器角色

public class ObjectAdapter {
    private Adaptee adaptee;
    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    /**
     * 源类Adaptee有方法sampleOperation1
     * 因此适配器类直接委派即可
     */
    public void sampleOperation1() {
        this.adaptee.sampleOperation1();
    }
    /**
     * 源类Adaptee没有方法sampleOperation2
     * 因此由适配器类需要补充此方法
     */
    public void sampleOperation2() {
        System.out.println("ObjectAdapter.sampleOperation2()");
    }
}

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

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

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

在 Android 开发过程中, ListView 的 Adapter 是我们最为常见的类型之一。

适配器模式的优缺点

优点:更好的复用性、更好的扩展性。
缺点:过多的使用适配器,会让系统非常零乱,不易整体进行把握。

本文实现源码https://github.com/wshunli/design-patterns/tree/master/src/ch07

参考资料
1、《JAVA与模式》之适配器模式 - java_my_life - 博客园
http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html
2、JAVA学习笔记—策略设计模式与适配器模式 - tongye - 博客园
https://www.cnblogs.com/tongye/p/6676039.html

如果本文对您有所帮助,且您手头还很宽裕,欢迎打赏赞助我,以支付网站服务器和域名费用。 https://paypal.me/wshunli 您的鼓励与支持是我更新的最大动力,我会铭记于心,倾于博客。
本文链接:https://www.wshunli.com/posts/69ceed63.html