0
点赞
收藏
分享

微信扫一扫

《设计模式入门》7.适配器模式

青青子衿谈育儿 2022-03-10 阅读 26

适配器模式的主要作用就是把原本不兼容的接口,通过适配修改做到统一。比如美版和港版电脑的插头与国行不一样,所以我们需要更换电源适配器,或者增加一个转换插头来解决问题。

适配器模式一般分为三种:

1.类适配器模式:

一个类转换成满足另一个新接口的类

创建一个新类,继承原有的类,实现新的接口

2.对象适配器模式:

一个对象转换成满足另一个新接口的对象

创建一个Wrapper类,持有原类的一个实例,在Wrapper类中调动实例的方法

3.接口适配器模式:

当不希望实现一个接口中所有的方法时

可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类。

=========================================================================

我们结合一个场景来看看具体的实现:

        假设一个场景,我们现在有一个美版电脑需要充电,但是我们只有国标的充电头,如何实现一个适配充电。

=========================================================================

首先定义两个接口,一个是国标接口,一个是美标接口。

国标接口:

package AdapterPattern.Dao;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PowerAdapterC.java
 * @Description 国标接口
 * @createTime 2022年03月01日 14:03:00
 */
public interface PowerAdapterC{
    /**
     * 插座类型
     * @return 充电类型
     */
    public String chargeType();
    /**
     * 充电功能
     */
    public void charge();
}

美标接口:

package AdapterPattern.Dao;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PowerAdapterA.java
 * @Description 美标
 * @createTime 2022年03月01日 14:09:00
 */
public interface PowerAdapterA {
    /**
     * 插座类型
     * @return 充电类型
     */
    public String chargeType();

    /**
     * 充电功能
     */
    public void charge();
}

定义一个电脑类,实现充电功能:

package AdapterPattern.Dao;

import AdapterPattern.Dao.impl.PowerAdapterAImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Computer.java
 * @Description 模拟电脑充电
 * @createTime 2022年03月01日 14:20:00
 */
public class Computer <T>{
    public void charging(T t){
        if (t instanceof PowerAdapterA) {
            System.out.println("开始充电");
            new PowerAdapterAImpl();
            PowerAdapterA powerAdapter;
            powerAdapter = (PowerAdapterA) t;
            powerAdapter.charge();
            System.out.println(powerAdapter.chargeType());
        }else {
            System.out.println("接口不匹配");
        }
    }
}

两个实现类,实现接口:

国标实现类:

package AdapterPattern.Dao.impl;

import AdapterPattern.Dao.PowerAdapterC;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PowerAdapterCImpl.java
 * @Description 国标转化器实现类
 * @createTime 2022年03月01日 14:18:00
 */
public class PowerAdapterCImpl implements PowerAdapterC {
    @Override
    public String chargeType() {
        return "Type-C";
    }

    @Override
    public void charge() {
        System.out.println("国标充电中======");
    }
}

美标实现类:

package AdapterPattern.Dao.impl;

import AdapterPattern.Dao.PowerAdapterA;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PowerAdapterAImpl.java
 * @Description 美标转换器实现类
 * @createTime 2022年03月01日 14:17:00
 */
public class PowerAdapterAImpl implements PowerAdapterA {
    @Override
    public String chargeType() {

        return "Type-A";
    }

    @Override
    public void charge() {
        System.out.println("美标充电中+++++++++");
    }
}

=========================================================================

我们分别用三种适配器来实现

=========================================================================

类适配器模式:

通过多重继承目标接口和被适配者类方式来实现适配。

package AdapterPattern.ClassAdapter;

import AdapterPattern.Dao.PowerAdapterA;
import AdapterPattern.Dao.impl.PowerAdapterCImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PowerAdapterC2A.java
 * @Description 国标适配器转美标
 * @createTime 2022年03月01日 14:07:00
 */
public class ClassPowerAdapterC2A extends PowerAdapterCImpl implements PowerAdapterA {
    //我们用C去适配A,所以集成C的实现类,并且同时实现A的接口。
    @Override
    public void charge() {
        super.charge();
    }
}

测试类:

package AdapterPattern.ClassAdapter;

import AdapterPattern.Dao.Computer;
import AdapterPattern.Dao.PowerAdapterA;
import AdapterPattern.Dao.PowerAdapterC;
import AdapterPattern.Dao.impl.PowerAdapterCImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ClassAdapterTest.java
 * @Description 转换器测试
 * @createTime 2022年03月01日 14:23:00
 */
public class ClassAdapterTest {
    public static void main(String[] args) {
        PowerAdapterA powerAdapter = new ClassPowerAdapterC2A();
        Computer<Object> computer = new Computer<>();
        computer.charging(powerAdapter);
    }
}

         我们可以看到,虽然电脑需要适配美标插头,但是经过我们的适配器,就可以用国标插头来充电了

=========================================================================

对象适配器模式

对象适配器和类适配器使用了不同的方法实现适配,对象适配器使用组合,类适配器使用继承。

package AdapterPattern.ObjectAdapter;

import AdapterPattern.Dao.PowerAdapterA;
import AdapterPattern.Dao.PowerAdapterC;
import AdapterPattern.Dao.impl.PowerAdapterCImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ObjectPowerAdapterC2A.java
 * @Description 国标适配器转美标
 * @createTime 2022年03月01日 14:39:00
 */
public class ObjectPowerAdapterC2A implements PowerAdapterA {
    PowerAdapterC powerAdapter= new PowerAdapterCImpl();

    @Override
    public String chargeType() {
        return powerAdapter.chargeType();
    }

    @Override
    public void charge() {
        powerAdapter.charge();
    }
}

        我们的适配器实现类美标充电接口,说明适配器类型是美标的,但是在适配器中创建了一个国标适配器的对象,然后返回国标对象的执行结果。(这何尝不是一种。。。。)

测试一下:

package AdapterPattern.ObjectAdapter;

import AdapterPattern.Dao.Computer;
import AdapterPattern.Dao.PowerAdapterA;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ObjectAdapterTest.java
 * @Description 对象适配器模式测试
 * @createTime 2022年03月01日 14:41:00
 */
public class ObjectAdapterTest {
    public static void main(String[] args) {
        PowerAdapterA powerAdapter = new ObjectPowerAdapterC2A();
        Computer<Object> computer = new Computer<>();
        computer.charging(powerAdapter);
    }
}

 =========================================================================

接口适配器模式

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

我们先写一个适配器的抽象类,并且添加两个方法(可能是实现的接口中的方法复写出来的):

package AdapterPattern.InterfaceAdapter;

import AdapterPattern.Dao.PowerAdapterA;
import AdapterPattern.Dao.PowerAdapterC;
import AdapterPattern.Dao.impl.PowerAdapterCImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName InterfaceAdapterC2A.java
 * @Description 适配器抽象类
 * @createTime 2022年03月01日 15:18:00
 */
public abstract class InterfaceAdapterC2A implements PowerAdapterA {
    PowerAdapterC powerAdapter = new PowerAdapterCImpl();

    @Override
    public void charge() {
        powerAdapter.charge();
    }

    @Override
    public String chargeType() {
        return powerAdapter.chargeType();
    }

    /**
     * 新方法
     */
    public void b(){
        System.out.println("bbbbbbbbbbbbb");
    }

    /**
     * 新方法
     */
    public void c(){

    }
}

通过实现类去实现适配器,我们只需要charge和chargeType两个方法,所以我们选择性实现两个:

package AdapterPattern.InterfaceAdapter;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName InterfaceAdapterC2AImpl.java
 * @Description 适配器实现类
 * @createTime 2022年03月01日 15:20:00
 */
public class InterfaceAdapterC2AImpl extends InterfaceAdapterC2A {
    @Override
    public void charge() {
        super.charge();
    }

    @Override
    public String chargeType() {
        return super.chargeType();
    }
}

测试一下:

package AdapterPattern.InterfaceAdapter;

import AdapterPattern.ClassAdapter.ClassPowerAdapterC2A;
import AdapterPattern.Dao.Computer;
import AdapterPattern.Dao.PowerAdapterA;
import AdapterPattern.Dao.PowerAdapterC;
import AdapterPattern.Dao.impl.PowerAdapterCImpl;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ClassAdapterTest.java
 * @Description 转换器测试
 * @createTime 2022年03月01日 14:23:00
 */
public class InterfaceAdapterTest {
    public static void main(String[] args) {
        PowerAdapterA powerAdapter = new InterfaceAdapterC2AImpl();
        Computer<Object> computer = new Computer<>();
        computer.charging(powerAdapter);
    }
}

  ========================================================================

优点:

  •  将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
  •  增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
  •  灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

缺点:

  • 对于类适配器,JAVA不支持多继承,所以适配有一定的局限性。
  • 对于对象适配器,相对类适配器,更换适配者类的方法就不容易,实现过程较为复杂。
举报

相关推荐

0 条评论