设计模式之适配器模式

概述

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)

这种模式涉及到一个单一的类,该类负责加入独立或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

主要分为三类:类适配器模式、对象的适配器模式、接口的适配器模式

适配器的流程类似如下:需要被适配的->Adapter->最终想要的

特点:

1、可以让任何两个没有关联的类一起运行。

2、提高了类的复用。

3、增加了类的透明度。

4、灵活性好。

注意:适配器不是在详细设计时添加的,主要是解决正在服役的项目的问题。

使用场景

  1. 系统需要使用现有的类,而这些类的接口不符合系统的需要。
  2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
  3. 需要一个统一的输出接口,而输入端的类型不可预知。

在实际使用中无需过于拘泥于以下设计模式的例子,可根据实际业务需要进行设计。

电压类适配器示例

场景:充电器例子,需要将220v的电压转换为5v的电压。

需要被适配已有220v电压的类

/**
 * 需要适配已有220v电压的类
 */
static class Voltage220 {

    public int output220V(){
        System.out.println("输出220v电压");
        return 220;
    }
}

需要的5v的接口

/**
 * 需要的5v的接口
 */
interface Voltage5 {
    /**
     * 需要输出5v电压
     */
    int output5V();
}

电压适配器

/**
 * 适配器
 */
static class VoltageAdapter extends Voltage220 implements Voltage5 {

    @Override
    public int output5V() {
        // 将输入5v的参数转为220v的获取执行结果
        int voltage = output220V();
        // 将结果转换为5v需要的返回结果
        System.out.println("适配器开始工作,转换电压为5v");
        return voltage/44;
    }
}

使用

public static void main(String[] args) {
    // 创建Voltage5时使用适配器来创建
    Voltage5 voltage5 = new VoltageAdapter();
    int voltage = voltage5.output5V();
    if (voltage==5){
        System.out.println("电压适配成功,开始充电");
    }else {
        System.out.println("电压适配失败,充电器即将爆炸,请马上断开电源");
    }
}

类适配器,让Adapter继承需要被适配的的类,在里面对其进行处理;由于Java的单继承机制,其使用成本也增加了;

对象适配器

/**
 * 需要的5v的接口
 */
interface Voltage5 {
    /**
     * 需要输出5v电压
     */
    int output5V();
}

/**
 * 需要适配已有220v电压的类
 */
static class Voltage220 {

    public int output220V(){
        System.out.println("输出220v电压");
        return 220;
    }
}

static class VoltageAdapter implements Voltage5 {

    private Voltage220 voltage220;
    // 让适配器持有需要适配的对象
    public VoltageAdapter(Voltage220 voltage220){
        this.voltage220 = voltage220;
    }

    @Override
    public int output5V() {
        int voltage = voltage220.output220V();
        System.out.println("适配器开始工作,转换电压为5v");
        return voltage/44;
    }
}

使用

public static void main(String[] args) {
    VoltageAdapter voltageAdapter = new VoltageAdapter(new Voltage220());
    int voltage = voltageAdapter.output5V();
    if (voltage==5){
        System.out.println("电压适配成功,开始充电");
    }else {
        System.out.println("电压适配失败,充电器即将爆炸,请马上断开电源");
    }
}

将对象传递给适配器

接口适配器

interface WxPay {

    void pay();

    void refund();

}

static abstract class WxPayAdapter implements WxPay {
    @Override
    public void pay(){

    }

    @Override
    public void refund(){

    }
}

使用

public static void main(String[] args) {

    WxPay wxPay = new WxPay() {
        @Override
        public void pay() {
            System.out.println("支付实现");
        }

        @Override
        public void refund() {
            System.out.println("退款实现");
        }
    };
    wxPay.pay();

    // 使用适配器后只需要实现我们需要的即可
    WxPayAdapter wxPayAdapter = new WxPayAdapter() {
        @Override
        public void pay() {
            System.out.println("支付实现");
        }
    };
    wxPayAdapter.pay();
}

以接口为目标的适配器;这种方式在安卓中非常常见,比如添加相关的监听器,我只需要实现我们需要的即可,对应不需要的无需去实现,简化了代码。

接口升级兼容示例

未使用设计模式时

public class NoAdapterPattern {

    public static void main(String[] args) {
        MediaPlayerV1 oldObject = new MediaPlayerV1Impl();
        MediaPlayerV2 newObject = new MediaPlayerV2Impl();
        oldObject.play();
        newObject.play();
    }

    /**
    * v1版本接口
    */
    public static interface MediaPlayerV1 {

        void play();
    }

    /**
    * v1版本接口实现类
    */
    public static class MediaPlayerV1Impl implements MediaPlayerV1 {

        @Override
        public void play() {
            System.out.println("播放mp3");
        }
    }

    /**
    * v2版本接口
    */
    public static interface MediaPlayerV2 {

        void play();
    }

    /**
    * v2版本接口实现类
    *
    */
    public static class MediaPlayerV2Impl implements MediaPlayerV2 {
        @Override
        public void play() {
            System.out.println("播放mp4");
        }
    }
}

使用类适配器模式

public class AdapterPatter {

    public static void main(String[] args) {
        // 将v1版本的转换为v2版本的接口
        MediaPlayerV2 oldObject = new NewInterfaceAdapter();
        MediaPlayerV2 newObject = new MediaPlayerV2Impl();
        oldObject.play();
        newObject.play();
    }

    /**
    * 定义一个适配器类
    */
    public static class NewInterfaceAdapter implements MediaPlayerV2 {

        private final MediaPlayerV1 v1;

        public NewInterfaceAdapter(){
            this.v1 = new MediaPlayerV1Impl();
        }

        @Override
        public void play() {
            // 实际调用v1版本的实现
            this.v1.play();
        }
    }


    /**
    * v1版本接口
    */
    public static interface MediaPlayerV1 {

        void play();
    }

    /**
    * v1版本接口实现类
    */
    public static class MediaPlayerV1Impl implements MediaPlayerV1 {

        @Override
        public void play() {
            System.out.println("播放mp3");
        }
    }

    /**
    * v2版本接口
    */
    public static interface MediaPlayerV2 {

        void play();
    }

    /**
    * v2版本接口实现类
    */
    public static class MediaPlayerV2Impl implements MediaPlayerV2 {
        @Override
        public void play() {
            System.out.println("播放mp4");
        }
    }
}

适配器的新接口方法的实现,全部基于老接口实现类的老方法来实现即可;对于调用方,只要使用适配器来开发即可,就可以通过面向新接口开发,底层使用老接口实现类。

posted @ 2020-09-25 23:03  起岸星辰  阅读(130)  评论(0编辑  收藏  举报