适配器模式

Author Avatar
丁起男 04月 26,2021
  • 在其它设备中阅读本文章

适配器模式

  • 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能在一起工作的两个类可以协同工作。其别名为包装器
  • 适配器模式属于结构型模式
  • 主要分为三类:类适配器模式、对象适配器模式和接口适配器模式

工作原理

  • 适配器模式:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容
  • 从用户的角度看不到被适配者,是解耦的
  • 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法
  • 用户收到反馈结果,感觉只是和目标接口交互

类适配器

adapter类,通过继承src类,实现dst类接口,完成src->dst的适配

src类

//被适配的类
public class Voltage220v{
    
    //输出220v电压
    public int output220v(){
        int src = 220;
        System.out.println("电压="+src+"伏");
        return src;
    }
}

dst类

//适配接口
public interface IVoltage5V{
    public int output5v();
}

adapter类

//适配器
public class VoltageAdapter extends Voltage220v implements IVoltage5v{
    
    @Overide
    public int output5v(){
        //获取220v电压
        int src220v = output220v();
        //转换成5v
        int dst5v = src220v / 44;
        return dst5v;
    }
}

使用类:

public class Phone{
    //充电
    public void charging(IVoltage5v iVoltage5v){
        if(iVoltage5v.output5v()==5){
            System.out.println("可以充电");
        }
    }
}

测试:

Phone phone = new Phone();
phone.charging(new VoltageAdapter());

注意事项:

  • java是单继承机制,所以类适配器需要继承src类这一点是一个缺点,因为者要求dst必须是接口,有一定局限性
  • src类的方法再adapter中都会暴露出来,也增加了使用成本
  • 由于其继承了src类,所以它可以根据需求重写src类的方法,使得adapter的灵活性增强了

对象适配器

  • 基本思路和类的适配器模式相同,只是将adapter类作修改,不是继承src类,而且持有src类的实例,已解决兼容性问题。即:持有src类,实现dst类接口,完成src->dst的适配
  • 根据合成复用原则,再系统中尽量使用关联关系来替代继承关系

adapter:

//适配器
public class VoltageAdapter implements IVoltage5v{
    
    //持有src对象,而不是继承(聚合关系)
    private Voltage220v voltage220v;
    
    public VoltageAdapter(Voltage220v voltage220v){
        this.voltage220v = voltage220v;
    }
    
    @Overide
    public int output5v(){
        //获取220v电压
        int src220v = voltage220v.output220v();
        //转换成5v
        int dst5v = src220v / 44;
        return dst5v;
    }
}

注意事项:

  • 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。

    根据合成复用原则,使用组合替代继承,所以它解决了类适配器必须继承src的局限性问题,也不要去dst必须是接口

  • 使用成本更低,更灵活

接口适配器

  • 也叫缺省适配器模式
  • 当不需要全部实现接口提供的方法时,可以先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择的覆盖父类的某些方法来实现需求
  • 适用于一个接口不想使用其所有的方法的情况

接口:

public interface MyInterface{
    void fun1();
    void fun2();
    void fun3();
    void fun4();
}

抽象类(适配器):

//将接口中的方法进行空实现
public abstract class AbsAdapter implements MyInterface{
    @Overide
    public void fun1(){}
    @Overide
    public void fun2(){}
    @Overide
    public void fun3(){}
    @Overide
    public void fun4(){}
}

使用:

public class MyImpl extends AbsAdapter{
    //只覆盖自己关系的方法
    @Overide
    public void fun2(){
        ...
    }
}

总结

  • 三种命名方式:是根据src(被适配的类)是以怎样的形式给到adapter的(在adapter中的形式)
    • 类适配器:以类给到adapter里,就是将src当作类,继承
    • 对象适配器:以对象给到adapter里,将src作为一个对象,持有
    • 接口适配器:以接口给到adapter里,将src作为一个接口,实现
  • 适配器模式最大的作用还是将原本不兼容的接口融合在一起工作