设计模式——适配器模式

269 阅读3分钟

一、概述

什么是适配器?比如笔记本电脑的电源适配器、手机的充电头,就是供电电压变换设备,使得我们的设备是正常的供电电压;一个墙上插座的插孔只有一个三孔的,而我们手机的充电头是两孔的,那么我们就需要一个插板,才能让我们的手机充上电,所以这个插板就是一个适配器角色;Android控件中的ListView、GridView、RecyclerView等列表组件,也是通过Adapter适配器,使得数据Data与定制的View视图联系起来,展示在列表组件中去。

适配器模式就是把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作,适配器模式是一种结构型的设计模式。适配器模式主要有3个角色:

  • 适配者(Adaptee):需要被适配的对象或类型,这里相当于家庭220V电压;
  • 适配器(Adapter):连接目标和源的中间对象,这里相当于手机充电头;
  • 目标(Target):期待得到的目标,手机充电的电压5V。

适配器模式有对象适配器和类适配器,下面分别用代码进行说明。

二、使用

1、类适配器

就用手机充电的例子,首先创建一个通用电压的接口。

/**
 * 通用接口
 */
public interface VoltageCommon {
    //输出220V电压
    int output220Voltage();
}

其次创建家庭220V的电压适配类,也就是需要被适配的对象。

/**
 * 家庭220V电压——被适配的类
 */
public class HomeUse implements VoltageCommon {

    @Override
    public int output220Voltage() {
        return 220;
    }
}

然后需要创建一个目标角色,也就是手机充电的电压接口。

/**
 * 手机电压
 */
public interface PhoneVoltage {
    //输出5V电压
    int output5Voltage();
}

最后创建适配器角色,把家庭电压转化成手机充电电压。

/**
 * 电压适配器 ——(类适配器)
 */
public class VoltageClassAdapter extends HomeUse implements PhoneVoltage {

    @Override
    public int output5Voltage() {
        int home = output220Voltage();
        return home / 44;
    }
}

进行代码测试,输出如下图所示。

VoltageCommon voltage = new HomeUse();
int v = voltage.output220Voltage();
showResult(v);
v = new VoltageClassAdapter().output5Voltage();
showResult(v);


private void showResult(int v){
    Log.e(TAG, "当前电压:" + v);
    if(v > 5){
        Log.e(TAG, "超过正常充电电压,无法充电");
    }else{
        Log.e(TAG, "电压正常,开始充电");
    }
}

2、对象适配器

对象适配器主要是通过组合来实现适配器功能的,其基本思路和类适配器大同小异,只是需要修改适配器类(VoltageClassAdapter类),不通过继承适配者,还是持有适配者的引用。所以我们只需要修改VoltageClassAdapter类即可,其他类的代码不用改动。

/**
 * 电压适配器 ——(对象适配器)
 */
public class VoltageObjectAdapter implements PhoneVoltage {

    private HomeUse homeUse;

    public VoltageObjectAdapter(HomeUse homeUse){
        this.homeUse = homeUse;
    }

    @Override
    public int output5Voltage() {
        int home = homeUse.output220Voltage();
        return home / 44;
    }
}

进行测试一下,代码结果输出如下图所示。可以看到结果和使用类适配器是一样的。

VoltageCommon voltage = new HomeUse();
int v = voltage.output220Voltage();
showResult(v);
v = new VoltageObjectAdapter(voltage).output5Voltage();
showResult(v);

private void showResult(int v){
    Log.e(TAG, "当前电压:" + v);
    if(v > 5){
        Log.e(TAG, "超过正常充电电压,无法充电");
    }else{
        Log.e(TAG, "电压正常,开始充电");
    }
}

三、总结

适配器模式具有更好的复用性和扩展性,最大的作用还是将原本不兼容的接口融合在一起工作。在对象适配器中我们可以看出有一丝静态代理模式的味道,但这和静态代理有很大的区别,不光是代码层面,思想层面也有大不同。当然,如果过度使用适配器模式,会让系统非常凌乱,不易整体把握。

github地址:github.com/leewell5717…

四、参考

java适配器模式

JAVA设计模式——适配器模式