12/24 设计模式之适配器模式 Adapter Pattern

763 阅读2分钟

类别:结构型设计模式

目的:将历史遗留代码(通常是一个library)/三方代码转换成一个新接口,使得可以在使用这个新接口的项目中使用

完整代码参考:1drv.ms/u/s!AquRvPz…

典型场景

这里拿一个系统中的支付模块举例,一个支付模块会对接多个支付比如微信,支付宝等

基本事实

在现有代码中,已在使用一种支付方式处理订单,对应的支付接口Pay.java参考如下

public interface Pay {
    void setAmount(Integer amount);
    void makePayment();
}

上面这个接口的实现PayImpl.java

public class PayImpl implements Pay {
    @Override
    public void setAmount(Integer amount) {
        System.out.println("set pay impl");
    }

    @Override
    public void makePayment() {
        System.out.println("make payment");
    }
}

serviceMyService.java中使用支付方式处理订单,参考如下:

public class MyService {
    public void processOrder(Pay pay) {
        pay.setAmount(1);
        pay.makePayment();
    }
}

调用参考

var myservice = new MyService();
var pay = new PayImpl();
myservice.processOrder(pay);

运行效果如下:

-w323
可以看到现有支付调用是ok的

接入一个新的支付方式

新的支付方式比如Pay1的接口Pay1.service参考如下:

public interface Pay1 {
    void init();
    void setPrice(Integer amount);
    void processPay();
}

对应实现Pay1Impl.java

public class Pay1Impl implements Pay1 {
    @Override
    public void init() {
        System.out.println("pay1 init");
    }

    @Override
    public void setPrice(Integer amount) {
        System.out.println("pay1 set amount");
    }

    @Override
    public void processPay() {
        System.out.println("pay1 make payment");
    }
}

和现存支付接口对比

Pay1.java Pay.java
init 不存在
setPrice setAmount
processPay makePayment

可以看到被使用的第三方支付方式的接口和项目中现存的不一样,这样就不能在MyService中直接使用了(参考编辑器的提示)

-w745
这种情况就可以使用适配模式了

模式实现

就是将需要新增的三方支付方式Pay1适配成目前项目需要的Pay,新增一个类比如Pay1Adapter进行接口转换

Pay1Adapter.java参考如下:

public class Pay1Adapter implements Pay {
    private Pay1 pay1;
    
    public Pay1Adapter(Pay1 pay1) {
        this.pay1 = pay1;
    }

    @Override
    public void setAmount(Integer amount) {
        pay1.init();
        pay1.setPrice(amount);
    }

    @Override
    public void makePayment() {
        pay1.processPay();
    }
}

适配效果如下

-w551

可以看到经过适配后,Pay1可以在需要Pay接口的项目中使用了

这个将Pay1接口转成Pay接口的Pay1Adapter就是适配器

UML

-w721

为什么要使用适配器

  1. 尽可能使用最少的代码复用三方代码
  2. 避免直接修改三方代码

一些注意的点

一般三方sdk不会为某个系统单独进行适配,就需要自行进行适配了

参考资料

  1. www.geeksforgeeks.org/adapter-pat…