crazyandcoder

设计模式教程(8-适配器模式)

2021.07.12

适配器模式.png

1 定义

适配器模式 (Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器 (Wrapper)。在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器 (Adapter),它所包装的对象就是适配者 (Adaptee),即被适配的类。适配器模式主要分为两大类:

  1. 类结构型模式,
  2. 对象结构型模式。

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

2 分类

2.1 类结构型模式

适配器模式(Adapter)包含以下主要角色:

  1. 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  2. 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  3. 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

2.1.1 UML 类图

类.gif

2.1.2 代码示例

Target
public interface Target {
    void request();
}
Adaptee
public class Adaptee {
    protected void specialRequest() {
        System.out.println("Adaptee specialRequest!!");
    }
}
ClassAdapter
public class ClassAdapter extends Adaptee implements Target {

    @Override
    public void request() {
        System.out.println("ClassAdapter request before");
        specialRequest();
        System.out.println("ClassAdapter request after");
    }
}
ClassAdapterTest
public class ClassAdapterTest {
    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request();
    }
}
打印
ClassAdapter request before
Adaptee specialRequest!!
ClassAdapter request after

2.2 对象结构型模式

适配器模式(Adapter)包含以下主要角色:

  1. 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  2. 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  3. 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

2.2.1 UML 类图

对象.gif

2.2.2 代码示例

Target
public interface Target {
    void request();
}
Adaptee
public class Adaptee {
    protected void specialRequest() {
        System.out.println("ObjectAdapter Adaptee specialRequest!!");
    }
}
ObjectAdapter
public class ObjectAdapter extends Adaptee implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        System.out.println("ObjectAdapter request before");
        adaptee.specialRequest();
        System.out.println("ObjectAdapter request after");
    }
}
ObjectAdapterTest
public class ObjectAdapterTest {
    public static void main(String[] args) {
        Adaptee objectAdaptee=new Adaptee();
        Target target = new ObjectAdapter(objectAdaptee);
        target.request();
    }
}
打印
ObjectAdapter request before
ObjectAdapter Adaptee specialRequest!!
ObjectAdapter request after

3 优缺点

3.1 优点

  1. 更好的复用性,系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
  2. 更好的扩展性,在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。

3.2 缺点

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