Java设计模式(七)结构型- 适配器模式Adapter Class/Object(史上最全适配器模式类/ 对象/接口适配)与使用场景以及优缺点

  1. 适配器模式

适配器模式,它的功能是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作。适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配> - 者接口转换成目标接口,让客户按目标接口的格式访问适配者。

1.1 类适配器

类适配器是通过定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件来实现的,类图如下:

Java设计模式(七)结构型- 适配器模式Adapter Class/Object(史上最全适配器模式类/ 对象/接口适配)与使用场景以及优缺点_第1张图片

// 适配者 220V电压
public class AC220 {
    public int output() {
        System.out.println("输出220V交流电");
        return 220;
    }
}
// 目标 5V
public interface DC5 {
    public int output5();
}
// 适配器类(电源适配器)
public class PowerAdapter extends AC220 implements DC5 {
    @Override
    public int output5() {
        int output220 = super.output();
        int output5 = output220 / 44;
        System.out.println(output220 + "V适配转换成" + output5 + "V");
        return output5;
    }
}
    // 测试
    public static void main(String[] args) {
        PowerAdapter powerAdapter = new PowerAdapter();
        // 输出220V交流电
        powerAdapter.output();
        // 输出220V交流电
        // 220V适配转换成5V
        powerAdapter.output5();
    }

通过上面代码例子可以看出,类适配器有一个很明显的缺点,就是违背了合成复用原则。结合上面的例子,假如我不是220V的电压了,是380V电压呢?那就要多建一个380V电压的适配器了。同理,由于Java是单继承的原因,如果不断的新增适配者,那么就要无限的新增适配器,于是就有了对象适配器。

1.2 对象适配器

对象适配器的实现方式是通过现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

// 电源接口
public interface Power {
    int output();
}
// 适配者 220V电压
public class AC220 implements Power {
    @Override
    public int output() {
        System.out.println("输出220V交流电");
        return 220;
    }
}
// 目标 5V
public interface DC5 {
    public int output5();
}
@AllArgsConstructor
public class PowerAdapter implements DC5 {
 
    // 适配者
    private Power power;
    @Override
    public int output5() {
        int output220 = power.output();
        int output5 = output220 / 44;
        System.out.println(output220 + "V适配转换成" + output5 + "V");
        return output5;
    }
}
    // 测试
    public static void main(String[] args) {
        DC5 powerAdapter = new PowerAdapter(new AC220());
        // 输出220V交流电
        // 220V适配转换成5V
        powerAdapter.output5();
    }

可以看到,上面代码中,只实现了目标接口,并没有继承适配者,而是将适配者类实现适配者接口,在适配器中引入适配者接口,当我们需要使用不同的适配者通过适配器进行转换时,就无需再新建适配器类了,如上面例子,假如我需要380V的电源转换成5V的,那么客户端只需要调用适配器时传入380V电源的类即可,就无需再新建一个380V电源的适配器了(PS:上述逻辑代码中output220 / 44请忽略,可以根据实际情况编写实际的通用逻辑代码)。

1.3 接口适配器

接口适配器主要是解决类臃肿的问题,我们可以把所有相近的适配模式的方法都放到同一个接口里面,去实现所有方法,当客户端需要哪个方法直接调用哪个方法即可。如上面例子所示,我们只是转换成了5V电压,那假如我要转换成12V,24V,30V…呢?那按照上面的写法就需要新建12V,24V,30V…的接口,这样就会导致类过于多了。那么我们就可以把5V,12V,24V,30V…这些转换方法,通通都写到一个接口里去,这样当我们需要转换哪种就直接调用哪种即可。

// 这里例子 输出不同直流电接口
public interface DC {
    int output5();
    int output12();
    int output24();
    int output30();
}
// 适配器类(电源适配器)
@AllArgsConstructor
public class PowerAdapter implements DC {
    private Power power;
    @Override
    public int output5() {
        // 具体实现逻辑
        return 5;
    }
    @Override
    public int output12() {
        // 具体实现逻辑
        return 12;
    }
    @Override
    public int output24() {
        // 具体实现逻辑
        return 24;
    }
    @Override
    public int output30() {
        // 具体实现逻辑
        return 30;
    }
}

1.4 总结

适用场景:

  • 已经存在的类,它的方法和需求不匹配(方法结构相同或相似)的情况。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

优点:

  • 能提高类的透明性和复用,现有的类复用但不需要改变。
  • 目标类和适配器类解耦,提高程序的扩展性。
  • 在很多业务场景中符合开闭原则。

缺点:

  • 适配器编写过程需要全面考虑,可能会增加系统的复杂性。
  • 增加代码阅读难度,降级代码可读性,过多使用适配器会使系统代码变得凌乱。

你可能感兴趣的:(java设计模式,java,设计模式,适配器模式)