适配器模式

思考适配器模式

适配器模式通过转换已有的接口,达成目标需要的接口
适配器模式还可以将多种差异化接口适配成同一接口做统一输出

1.适配器模式的本质

适配器模式的本质是:转换匹配,复用功能。

适配器通过转换调用已有的实现,从而能把已有的实现匹配成需要的接口,使之能满足客户端的需要。也就是说转换匹配是手段,而复用已有的功能才是目的。

在进行转换匹配的过程中,适配器还可以在转换调用的前后实现一些功能处理,也就是实现智能的适配。

2.何时选用适配器模式

建议在以下情况中选用适配器模式。

  • 在系统开发过程中,可能会遇到需要使用第三方组件或库,但是这些组件或库的接口与当前系统的接口不兼容的情况。此时可以使用适配器模式,将第三方组件或库的接口转换成当前系统的接口,以便能够方便地集成和使用。

  • 当需要重用一个类,但是其接口与其他类不兼容时,也可以使用适配器模式。通过创建一个适配器来实现两个类的接口兼容,以便能够重用该类。

3.优缺点

适配器模式有如下优点

  • 适配器模式可以让原本不兼容的接口之间能够协同工作,提高代码的重用性和灵活性。

  • 适配器模式可以让客户端代码与具体类实现解耦,提高代码的可维护性和可扩展性。

  • 适配器模式可以隐藏系统的实现细节,提高系统的安全性和稳定性。

适配器模式有如下缺点

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

4.适配器模式的结构

在这里插入图片描述

  • Client:客户端,调用自己需要的领域接口 Target。
  • Target:定义客户端需要的跟特定领域相关的接口。
  • Adaptee:已经存在的接口,通常能满足客户端的功能要求,但是接口与客户端要求的特定领域接口不一致,需要被适配。
  • Adapter:适配器,把Adaptee适配成为Client需要的Target。

5.实现

在这里插入图片描述

对象适配

原理:通过组合来实现适配器功能。

对象适配器是指使用一个对象作为中间适配器,将一个接口转换成另一个接口。在对象适配器中,适配器持有一个被适配对象的引用,并将客户端的请求转发给被适配对象来实现适配。

模拟实现多种支付,现系统对接了微信支付和支付宝支付

/**
 * @description:支付接口
 */
public interface IPay {

    void pay(String orderId);
}

/**
 * @description:微信支付
 */
public class WeiXinPay implements IPay{
    
    @Override
    public void pay(String orderId) {
        System.out.println("调用微信支付接口,订单id:"+orderId);
    }
}

/**
 * @description:支付宝支付
 */
public class ZhiFuBaoPay implements IPay{
    
    @Override
    public void pay(String orderId) {
        System.out.println("调用支付宝支付接口,订单id:"+orderId);
    }
}

现加入银联支付,想通过pay()统一调用所有的支付方法,需要进行适配

/**
 * @description:银联支付
 */
public class YinLianPay{

    /**
     * 银联支付的方法名及参数同微信支付宝的支付方法不一样
     */
    public void orderPay(String orderId, String name) {
        System.out.println("调用银联支付接口,订单id:" + orderId);
    }
}

/**
 * @description:银联支付适配器
 */
public class YinLianAdapter implements IPay {

    //持有银联支付对象
    private YinLianPay yinLianPay;

    public YinLianAdapter(YinLianPay yinLianPay) {
        this.yinLianPay = yinLianPay;
    }

    @Override
    public void pay(String orderId) {
        System.out.println("调用银联支付适配器");
        yinLianPay.orderPay(orderId, "张三");
    }
}

测试类

public class PayClient {

    public static void main(String[] args) {
        //微信支付
        IPay weiXinPay=new WeiXinPay();
        weiXinPay.pay("10001");

        //支付宝支付
        IPay zhiFuBaoPay=new ZhiFuBaoPay();
        zhiFuBaoPay.pay("10002");

        //银联支付
        IPay yinLianPay=new YinLianAdapter(new YinLianPay());
        yinLianPay.pay("10003");
    }
}

结果

调用微信支付接口,订单id:10001
调用支付宝支付接口,订单id:10002
调用银联支付适配器
调用银联支付接口,订单id:10003
接口适配

原理:通过抽象类来实现适配,这种适配稍别于上面所述的适配。

接口适配器是指使用一个抽象类作为中间适配器,将一个接口转换成另一个接口。在接口适配器中,适配器实现了目标接口,并对目标接口的所有方法进行了空实现。然后,客户端只需要实现目标接口中需要的方法即可,不需要实现所有方法。

当存在这样一个接口,其中定义了N多的方法,而我们现在却只想使用其中的一个到几个方法,如果我们直接实现接口,那么我们要对所有的方法进行实现,哪怕我们仅仅是对不需要的方法进行置空(只写一对大括号,不做具体方法实现)也会导致这个类变得臃肿,调用也不方便,这时我们可以使用一个抽象类作为中间件,即适配器,用这个抽象类实现接口,而在抽象类中所有的方法都进行置空,那么我们在创建抽象类的继承类,而且重写我们需要使用的那几个方法即可。

/**
 * @description:A接口
 */
public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
    void f();
}

/**
 * @description:适配器,实现A接口但不实现
 */
public abstract class Adapter implements A {
    public void a(){}
    public void b(){}
    public void c(){}
    public void d(){}
    public void e(){}
    public void f(){}
}

/**
 * @description:重写需要的部分方法
 */
public class RealA extends Adapter{
    @Override
    public void a() {
        System.out.println("实现a方法");
    }

    @Override
    public void b() {
        System.out.println("实现b方法");
    }
}

public class AClient {
    public static void main(String[] args) {
        A realA = new RealA();
        //只有a,b方法实现了
        realA.a();
        realA.b();
        //c,d,e未实现
        realA.c();
        realA.d();
        realA.e();
    }
}

结果

实现a方法
实现b方法
类适配

原理:通过继承来实现适配器功能。

当我们要访问的接口A中没有我们想要的方法 ,却在另一个接口B中发现了合适的方法,我们又不能改变访问接口A,在这种情况下,我们可以定义一个适配器p来进行中转,这个适配器p要实现我们访问的接口A,这样我们就能继续访问当前接口A中的方法(虽然它目前不是我们的菜),然后再继承接口B的实现类BB,这样我们可以在适配器P中访问接口B的方法了,这时我们在适配器P中的接口A方法中直接引用BB中的合适方法,这样就完成了一个简单的类适配器。

在这里插入图片描述
手机充电口是typec,充电宝是usb口,使用转接器转接

/**
 * @description:usb接口
 */
public interface Usb {

    /**
     * 使用usb
     */
    void useUsb();
}

/**
 * @description:TypeC接口
 */
public interface TypeC {

    /**
     * 使用TypeC
     */
    void useTypeC();
}

/**
 * @description:usb实现类
 */
public class Usber implements Usb{
    @Override
    public void useUsb() {
        System.out.println("使用USB接口");
    }
}

适配器

/**
 * @description:TypeC适配器
 */
public class TypeCAdapter extends Usber implements TypeC{
    @Override
    public void useTypeC() {
        //将typc接口转换成usb接口
        useUsb();
    }
}

测试类

public class TypeCClient {

    public static void main(String[] args) {
        TypeC typeC = new TypeCAdapter();
        typeC.useTypeC();
    }
}

结果

使用USB接口
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值