Java设计模式-适配器模式(Adapter)

675 阅读3分钟

「这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战

定义

属于结构型模式,其主要作用是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

举例

比如说我们日常使用手机、电脑等都需要有电源才行,然而我们家庭使用的电源都是220v,手机接收的电源只有5v,很显然直接用220给手机充电是不行的。因此我们手机就会有一个充电插头(适配器),这样我们的220V(源),通过充电插头(适配器),就可以给我们手机(目标),进行充电了。

通过以上举例,我们可以得出,实现适配需要三个角色:

  • 源(Adaptee) :需要被适配的对象或类型,相当于220v电。
  • 适配器(Adapter) :连接目标和源的中间对象,相当于充电插头。
  • 目标(Target) :期待得到的目标,相当于手机充电口。

适配器分类

适配器模式包括3种形式:类适配器模式、对象适配器模式、接口适配器模式(或又称作缺省适配器模式)。

类适配器

从下面的结构图可以看出,Adaptee类并没有operation()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,我们把AdapteeTarget衔接起来。AdapterAdaptee继承关系,这决定了这是一个类适配器模式。 image.png

源(Adaptee)代码

class AdapteeClass{
    public int outpuut220v(){
        return 220;
    }
}

目标(Target)代码

interface TargetClass{
    int output5v();
}

适配器代码(Adapter)

class AdapterClass extends AdapteeClass implements TargetClass{

    @Override
    public int output5v() {
        int i=outpuut220v();
        System.out.println(String.format( "原始电压: %d v ‐ > 输出电压: %d v ",i,5 ));
        return 5;
    }
}

测试代码

public static void main(String[] args) {
    AdapterClass adpater=new AdapterClass();
    adpater.output5v();
}

image.png 可以看到在用适配的时候,可以获得源和目标的接口。

执行结果

image.png

对象适配器

从下面的结构图可以看出,Adaptee类并没有operation()方法,而客户端则期待这个方法。与类适配器模式一样,为使客户端能够使用Adaptee类,我们把Adaptee与Target衔接起来。但这里我们不继承Adaptee,而是把Adaptee封装进Adapter里。这里Adaptee与Adapter是组合关系。blog.csdn.net/mrkohaku/ar… image.png

源(Adaptee)代码

class Adaptee{
    public int output220v(){
        return 220;
    }
}

目标(Target)

interface Target{
    int output5v();
}

适配器

class Adapter implements Target{
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee){
        this.adaptee=adaptee;
    }
    @Override
    public int output5v() {
        //获得220v
        int i=adaptee.output220v();
        //进行转换处理
        System.out.println(String.format( "原始电压: %d v ‐ > 输出电压: %d v ",i,5 ));
        return 5;
    }
}

测试代码

public static void main(String[] args) {
    Adaptee adaptee=new Adaptee();
    Target target=new Adapter(adaptee);
    target.output5v();
}

image.png 可以看到适配仅可输出目标的方法。

执行结果

image.png

类适配器与对象适配器的区别

类适配器使用的是继承的方式,直接继承了Adaptee,所以无法对Adaptee的子类进行适配。

对象适配器使用的是组合的方式,·所以Adaptee及其子孙类都可以被适配。另外,对象适配器对于增加一些新行为非常方便,而且新增加的行为同时适用于所有的源。

基于组合/聚合优于继承的原则,使用对象适配器是更好的选择。但具体问题应该具体分析,某些情况可能使用类适配器会适合,最适合的才是最好的。

应用场景

1.当你希望使用某些现有类,但其接口与您的其他代码不兼容时,请使用适配器类。

2.当你希望重用几个现有的子类,这些子类缺少一些不能添加到超类中的公共功能时,请使用该模式。

缺点:
过多使用适配器,会使系统代码变得非常凌乱,本来调用的A接口,结果最终缺调用了B接口,如非必要,可以不适用适配器模式。