👉文章示例代码👈

定义

将一个类的接口转换成客户端期望的另一个接口。

适配器模式可以使原本接口不兼容的类可以一起工作。

两种模式

适配器模式有两种模式:

  • 对象适配器:采用组合方式进行类的委托
  • 类适配器:采用继承方式

三种角色

  • 目标角色(Target):客户端所期待的接口(也可以是具体类或者抽象类)。
  • 源角色(Adaptee):被适配者。已经存在的需要适配的接口或类。
  • 适配器(Adapter):将源接口转换成目标接口。只能是具体的类。

场景示例

笔者有一台吃灰蛮久的尼康相机。由于笔者的mbp只有Type-C接口,不能直接读取相机的内存卡。为此笔者还特地斥巨资买了个Type-C的扩展坞。

这里Type-C扩展坞作为内存卡和笔记本之间的适配器,只要将内存卡插入Type-C扩展坞的SD卡接口中,再将扩展坞接入到笔记本的Type-C接口中,我们就可以通过笔记本来读取内存卡中的内容。

也就是说扩展坞将笔记本的Type-C接口适配成SD卡接口。这样理解的话,SD卡接口即为我们的目标角色,Type-C接口为被适配者(即源角色),扩展坞为两者之间的适配器。

类适配器

这里先用类适配器的方式来实现下。

创建源角色

上述已经分析了,Type-C接口作为我们的源角色,代码如下:

/**
 * @author zhh
 * @description TypeC接口类
 * @date 2020-02-14 16:33
 */
public class TypeCInterface {

    /**
     * type-C读取
     */
    public void typeCRead() {
        System.out.println("Type-C接口读取...");
    }
}
创建目标角色

创建目标角色,也就是SD卡接口。

/**
 * @author zhh
 * @description SD卡接口
 * @date 2020-02-14 16:36
 */
public interface SDInterface {

    void sdRead();
}
创建适配器

这里的适配器即Typc-C扩展坞,继承源角色,实现目标接口。

/**
 * @author zhh
 * @description Type-C扩展坞
 * @date 2020-02-14 16:43
 */
public class TypeCDockStation extends TypeCInterface implements SDInterface {

    public void sdRead() {
        System.out.println("SD卡接口读取...");
        System.out.println("扩展坞转换");
        super.typeCRead();
    }
}
测试类及输出
/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-14 16:59
 */
public class Test {

    public static void main(String[] args) {
        SDInterface sdInterface = new TypeCDockStation();
        sdInterface.sdRead();
    }
}

测试类的输出结果如下:

SD卡接口读取…

扩展坞转换

Type-C接口读取…

类结构图

以上示例类的结构图如下所示

image.png

对象适配器

再来讲讲对象适配器方式的实现。

该方式中,目标角色和源角色并未发生改动,和上述类适配器方式中保持一致,这里就不做过多的代码粘贴了。

主要变化的是适配器类。

创建适配器
/**
 * @author zhh
 * @description
 * @date 2020-02-14 17:23
 */
public class TypeCDockStation implements SDInterface {

    private TypeCInterface typeCInterface;

    public TypeCDockStation(TypeCInterface typeCInterface) {
        this.typeCInterface = typeCInterface;
    }

    public void sdRead() {
        System.out.println("SD卡接口读取...");
        System.out.println("扩展坞转换");
        typeCInterface.typeCRead();
    }
}
测试类及输出
/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-14 16:59
 */
public class Test {

    public static void main(String[] args) {
        TypeCInterface typeCInterface = new TypeCInterface();
        SDInterface sdInterface = new TypeCDockStation(typeCInterface);
        sdInterface.sdRead();
    }
}

测试类的输出结果如下:

SD卡接口读取…

扩展坞转换

Type-C接口读取…

类结构图

以上示例类的结构图如下所示

image.png

总结

适用场景

  • 想使用一个已存在的类,但是该类的方法不符合接口需求。
  • 软件维护过程中,解决不同产品或者厂家功能类似而接口不同的情况。

优点

  • 提高类的透明性
  • 复用现有的类
  • 目标类和适配器类解耦,提高扩展性

缺点

  • 增加系统的复杂性
  • 增加系统代码可读难度

参考