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

1. 定义

将一个类的接口转换为客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类一起工作。

比如: 测试类必须使用A类,现在测试类需要在A类的基础上使用B类的一些功能,这时就出现了接口不兼容的问题,此时就可以使用适配器类,将B类与A类整合,适配器类具有了B类的功能,但是可以在定义时,声明为A类(具体通过继承父类或者实现接口的方式),对外表现为A接口,这样测试类就不需要修改使用和定义A类的代码。

具体参照之后的代码案例进行理解。

适配器模式分为类适配器模式对象适配器模式。类适配器模式采用了继承的方式实现适配器类,而对象适配器模式采用了组合或者聚合的方式实现适配器类。

前者类之间的耦合度比后者高,且要求使用者理解现有组件库的相关组件的内部结构,所以应用相对较少些。

另外还有一种适配器模式:接口适配器模式,当不希望实现一个接口中所有的方法时,可以创
建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

2. 适配器模式的结构

适配器模式主要包含一下主要角色:

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

3. 案例代码

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

案例场景

举一个简单的例子:假设我们有一个手机需要充电,他的充电器的充电头为PlugA,但是因为一些问题(自行脑补),电源需要经过充电头PlugB转换之后,才能给PlugA使用为手机充电。此时,就需要将PlugA与电源通过PlugB进行适配。可以通过适配器模式来模拟该场景,电源可以理解为测试类的充电操作。

可以参考代码理解。

3.1 类适配器模式

类适配器模式是通过继承的方式实现的,实现的类图如下:
在这里插入图片描述
其中:

  • PlugAPlugB为两个插头的接口,PlugAImplPlugBImpl为其实现类。
  • MobilePhone类为手机类,其中有一个充电的方法,其输入只接受PlugA类型的数据,代表了其只能通过PlugA充电。
  • PlugAAdapterPlugB类为适配器类,其继承了PlugBImpl,实现了PlugA接口。所以其具有的PlugBImpl的功能,并且其顶层类型可为PlugA,可供MobilePhone调用。
  • 所以在使用时,我们可以直接使用PlugAAdapterPlugB创建插头对象PlugA,该对象在内部已经经过PlugB的转换。

1.PlugAPlugB 接口:

public interface PlugA {
    /*
      适配者类的接口
     */

    // 实现方法插头A充电
    void ChargeFromPlugA();

}
public interface PlugB {
    /*
       目标接口
     */
    // 充电
    void ChargeFromPlugB();
}

2.接口的实现类

public class PlugAImpl implements PlugA{

    @Override
    public void ChargeFromPlugA() {
        System.out.println("用插头A充电");
    }
}
public class PlugBImpl implements PlugB{

    @Override
    public void ChargeFromPlugB() {
        System.out.println("用插头B转换");
    }
}

3.手机类

public class MobilePhone {

    //手机类

    //使用A接口充电
    public void ChargeFromPlugA(PlugA plugA){
        if(plugA == null){
            throw new NullPointerException("plug is not null!");
        }
        plugA.ChargeFromPlugA();
    }
}

4.适配器类

public class PlugAAdapterPlugB extends PlugBImpl implements PlugA{

    @Override
    public void ChargeFromPlugA() {

        ChargeFromPlugB();
        System.out.println("使用插头A充电");

    }
}

5.测试类

public class test {
    public static void main(String[] args) {

        System.out.println("===1.手机不使用转接头充电===");
        MobilePhone mobilePhone = new MobilePhone();
        mobilePhone.ChargeFromPlugA(new PlugAImpl());

        System.out.println("===2.手机使用转接头B转到A充电[类适配器模式]===");
        PlugA plugA = new PlugAAdapterPlugB();
        mobilePhone.ChargeFromPlugA(plugA);
    }
}

结果:
在这里插入图片描述

类适配器模式的思考
  • 类适配器模式违背了合成复用原则。
  • 类适配器模式在客户类即上例中PlugAImpl类有接口规范的时候可以使用,当没有的时候就无法这样实现了。

3.2 对象适配器模式

对象适配器模式采用组合或者聚合的方式实现适配器类,也就是说我们再需要PlugBImpl类时,可以通过聚合的方式,在适配器类内部创建PlugB类型的成员变量(当然创建PlugBImpl类型的变量也可以),然后通过构造方法将PlugB传入适配器类,适配器调用其方法,这样适配器就没有继承作用上的父类了。

如果客户端类即PlugAImpl在实现的时候,没有接口规范,那我们就可以直接采用对PlugAImpl继承的方式来实现适配器类,这样就避免了类适配器模式中因为继承了PlugBImpl,而PlugAImpl
类没有接口规范而造成的无法实现适配器的问题。

该种模式下的类图如下所示,就不再过多解释,其中处理图中的实现关系外,适配器类PlugAAdapterPlugB_instancePlugB是聚合关系,MobilePhonePlugA为依赖关系。

在这里插入图片描述

代码如下:
其他代码不变,只修改适配器类和测试类即可。

适配器类:

public class PlugAAdapterPlugB_instance implements PlugA{

    private PlugB plugB;

    public PlugAAdapterPlugB_instance(PlugB plugB) {
        this.plugB = plugB;
    }

    @Override
    public void ChargeFromPlugA() {
        plugB.ChargeFromPlugB();
        System.out.println("使用插头A充电");

    }
}

测试类:

public class test {
    public static void main(String[] args) {

        System.out.println("===1.手机不使用转接头充电===");
        MobilePhone mobilePhone = new MobilePhone();
        mobilePhone.ChargeFromPlugA(new PlugAImpl());

        System.out.println("===2.手机使用转接头B转到A充电[类适配器模式]===");
        PlugA plugA = new PlugAAdapterPlugB();
        mobilePhone.ChargeFromPlugA(plugA);

        System.out.println("===3.手机使用转接头B转到A充电[对象适配器模式]===");
        PlugA plugA2 = new PlugAAdapterPlugB_instance(new PlugBImpl());
        mobilePhone.ChargeFromPlugA(plugA);
    }
}

结果:
在这里插入图片描述

4. 应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山风wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值