适配器 - 结构

一、概述

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,它结合了两个独立接口的功能,

使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,属于结构型模式。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

eg: 读卡器是作为内存卡和笔记本之间的适配器,

内存卡  => 读卡器 => 笔记本

将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

 

分类:

   类适配器、对象适配器、接口适配器。

角色模型:

  目标接口(Target):该角色把其他类转换为我们期望的接口

  被适配者/源接口(Adaptee):  原有的接口,也是希望被改变的接口

  适配器(Adapter):  将被适配者和目标接口组合到一起的类

 如上示例:选取笔记本为主体,笔记本需要读取内存卡,则笔记本为目标接口,内存卡为被适配者,读卡器为适配器。

适配器模式结构图:

 

二、使用

1. 笔记本案例

现有一个apple笔记本(USB接口),和一个内存卡(SM接口),如何实现apple读取内存卡数据?

/**
 * 目标 Target
 */
class Apple {
    public void usb() {
        System.out.println("数据从usb接口输入");
    }
}

/**
 * 源 Adaptee
 */
interface Sm {
    void smType();
}

/**
 * 测试类*/
public class AdapterTest {
    public static void main(String[] args) {
        // 原始的apple读取usb接口数据
        Apple apple = new Apple();
        AdapterTest.client(apple);
    }

    /**
     * 客户端
     */
    public static void client(Apple apple) {
        System.out.println("========苹果笔记本读取数据=======");
        apple.usb();
    }
}

当然,如上的源

1.1 类适配器

原理:通过继承特性来实现

/**
 * 1.类适配器 Adapter
 */
class ReaderCard extends Apple implements Sm {
    @Override
    public void smType() {
        System.out.println("数据从SM接口输出");
    }

    @Override
    public void usb() {
        this.smType();
        super.usb();
    }
}

public class AdapterTest {
    public static void main(String[] args) {       
        // 1.采用类适配器后,读取sm接口数据
        ReaderCard readerCard = new ReaderCard();
        AdapterTest.client(readerCard);
    }
}

总结:类适配器通过创建一个适配器类,使这个适配器继承Target和Adaptee接口,来将原来并不兼容的目标接口和源接口关联在了一起,这样使得适配器同时具有了两个接口的功能。客户端使用时,原来是要求传入一个Apple接口(后代),现在适配器也是Apple的后代,可以直接传递(面向接口编程)。

1.2 对象适配器

原理:通过组合方式 + 构造注入的方式实现

/**
 * 2.对象适配器
 */
class ReaderCard2 extends Apple {
    // 组合
    private Sm sm;

    // 构造注入
    public ReaderCard2(Sm sm) {
        this.sm = sm;
    }

    @Override
    public void usb() {
        sm.smType();
        super.usb();
    }
}

public class AdapterTest {
    public static void main(String[] args) {       
        // 2.对象适配器
        ReaderCard2 readerCard2 = new ReaderCard2(() -> System.out.println("数据从SM接口输出"));
        AdapterTest.client(readerCard2);
    }
}

总结:对象适配器通过创建一个适配器类,实现Target接口,然后使用构造注入的方式注入Adaptee,这样适配器类就组合了两个不兼容的接口,客户端要求使用Target接口,适配器又是Target的后代,这样就可以直接传递,同时,通过注入将源关联起来。

1.3 类适配器

原理:可以认为是和类适配器是同一种。

 2. 案例二

都知道创建现在的第三种方式是通过实现Callable接口,那么它是如何和Thread关联上的?

public class CallableDemo {
    public static void main(String[] args) throws Exception {
        // 两个线程,一个main线程,一个AAA futureTask

        // FutureTask(Callable<V> callable)
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread());new Thread(futureTask, "AAA").start();
    }
}

class MyThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {return 1024;
    }
}

class MyThread1 implements Runnable{
    @Override
    public void run() {

    }
}

创建线程需要传入一个Runnable接口,并没有构造方法让你去传Callable接口,而你有的只是一个Callable结构的实例,那你咋办?你如何将Callable传递给Thread呢?

分析:接口支持多次实现,如果能找到一个类,这个类实现了Runnable接口,又实现了Callable接口,那么传递一个这样的类,即可解决问题,这就是适配器模式。

(1) 创建线程需要传递Runnable接口,即只需要是Runnable的 后代接口、后台接口的实现类都可以传递,RunnableFuture接口实现了Runnable接口,类FutureTask又实现了RunnableFuture接口,所以可以传递FutureTask类;

(2) FutureTask类的构造注入可以传递进去一个Callable接口,所以FutureTask可以整合Runnable和Callable接口;

 

  

参考:

适配器模式

适配器模式的理解和示例

Java设计模式之适配器模式

posted @ 2020-03-29 12:19  一帘幽梦&nn  阅读(335)  评论(0编辑  收藏  举报
点击查看具体代码内容