Skip to content

适配器设计模式能使接口不兼容的对象能够相互合作,是作为两个不兼容的接口之间的桥梁,属于结构型模式

应用场景分析

假如你正在开发一款股票市场监测程序, 它会从不同来源下载 XML 格式的股票数据, 然后向用户呈现出美观的图表。在开发过程中, 你决定在程序中整合一个第三方智能分析函数库。 但是遇到了一个问题, 那就是分析函数库只兼容 JSON 格式的数据。

整合分析函数库之前的程序结构

你无法 “直接” 使用分析函数库, 因为它所需的输入数据格式与你的程序不兼容。你可以修改程序库来支持 XML。 但是, 这可能需要修改部分依赖该程序库的现有代码。 甚至还有更糟糕的情况, 你可能根本没有程序库的源代码, 从而无法对其进行修改。

常见的几类适配器

  1. 类的适配器模式:想将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
  2. 对象的适配器模式:想将一个对象转换成满足另一个新接口的对象时,可以创建一个适配器类,持有原类的一个实例,在适配器类的方法中,调用实例的方法就行。
  3. 接口的适配器模式:不想实现一个接口中所有的方法时,可以创建一个Adapter,实现所有方法,在写别的类的时候,继承Adapter类即可。

接口的适配器模式

场景:不想实现一个接口中所有的方法时,可以创建一个Adapter,实现所有方法,在写别的类的时候,继承Adapter类即

新建一个支付网关

java
public interface PayGateway {

    /**
     * 下单
     */
    void unifiedorder();

    /**
     * 退款
     */
    void refund();

    /**
     * 查询支付状态
     */
    void query();

    /**
     * 发红包
     */
    void sendRedPack();
}

场景分析:现在我有一个类,想要实现PayGateway中的两个方法,如果使用 implements实现,其他的必须实现空方法,而空方法是没有意义的。

因此我们使用一个类来实现方法,后续的只需要继承即可适配器实现需要的方法即可。

==错误用法:==

java
public class ProductVideoOrder implements PayGateway{

    @Override
    public void unifiedorder() {
        System.out.println("下单");
    }

    @Override
    public void refund() {
        System.out.println("退款");
    }

    @Override
    public void query() {

    }

    @Override
    public void sendRedPack() {

    }
}

创建适配器

java
public class PayGatewayAdapter implements PayGateway{
    @Override
    public void unifiedorder() {

    }

    @Override
    public void refund() {

    }

    @Override
    public void query() {

    }

    @Override
    public void sendRedPack() {

    }
}

==正确用法==

java
public class ProductVideoOrder extends PayGatewayAdapter{

    @Override
    public void unifiedorder() {
        System.out.println("下单");
    }

    @Override
    public void refund() {
        System.out.println("退款");
    }
}

类的适配器模式

需求:有一个旧的类,功能稳定运行,如何在不修改旧的类的情况下新增功能?

应用场景

有个电商支付项目,里面有个登录功能,已经线上运行了。客户端A 调用生产环境的登录接口B,且线上稳定运行了好几年。某天,公司接到收购了别的公司的项目,需要把这套系统部署在起来,且收购的项目也有对应的客户端C,但是两个客户端和服务端的协议不一样。

需求:收购的项目客户端C,需要做公司原来的项目用户数据打通,连接公司的服务端登录接口B,你能想到几个解决方案?

  1. 修改就项目B的登录接口,兼容C客户端协议(可能影响线上接口,不稳定)
  2. 新增全新的登录接口F,采用C客户端协议(和旧的业务逻辑会重复)
  3. 新增一个转换协议接口,客户端C调用旧的B接口之前,使用转换接口转换下协议(适配器模式,推荐这个方式)

旧的类

java
public class OldModule {

    public void moduleA(){
        System.out.println("OldModule moduleA");
    }

}

接口——当做通信的桥梁

java
public interface TargetModule {

    /**
     * 和需要整合的类方法名一样
     */
    void moduleA();

    /**
     * 新的方法
     */
    void moduleB();

}

适配器

java
/**
 * 继承旧的类,实现接口,由于继承旧的类,旧的类中的方法就无需实现
 * @author cv大魔王
 * @version 1.0
 * @date 2021/7/12 19:22
 */
public class Adapter extends OldModule implements TargetModule{
    @Override
    public void moduleB() {
        System.out.println("Adapter ModuleB");
    }
}

使用:

java
public static void main(String[] args) {
    TargetModule targetModule = new Adapter();
    targetModule.moduleA();
    targetModule.moduleB();
}