从《大话设计模式》看JDK及框架中常用的设计模式(三)

文章目录

        • 适配器模式
          • 1.介绍
          • 2. 角色分配
          • 3.实例
          • 4.应用场景

适配器模式

1.介绍

适配器模式(Adapter Pattern):将一个类的接口转换成希望的另一个接口,让那些接口不兼容的类可以一起工作。

  • 如果需要复用已有的类,但是接口不兼容,不能或者不愿修改原有的类或者需要的类。可以使用适配器,用户在调用适配器的方法时在适配器的内部会调用适配者的方法。
  • 又称包装器模式。
2. 角色分配

角色包括:

  1. 目标抽象类(Target):定义用户需要的接口。
  2. 适配器类(Adapter):作为转换器调用另一个接口,使得目标类和适配者类联系。类适配器中,继承适配者实现目标类接口,对象适配器中,关联适配者,继承目标类。
  3. 适配者类(Adaptee):定义了一个已存在的接口,包含需要的业务方法,但是和需要的接口不兼容。

当你想使用一个已经存在的类,而它的接口不符合你的需求,或者你想创建一个可重用的类(与不兼容接口无关的类),这时候可以考虑使用适配器模式。同时它也是一种包装模式,它与装饰模式同样具有包装的功能。

从《大话设计模式》看JDK及框架中常用的设计模式(三)_第1张图片

3.实例

购买小米手机送一个type-c的转接口给我们,那会type-c数据线应该还不算普及,这种做法还是蛮好的,在使用转接口后Micro USB得以重复利用,这样一来即使原装的米5数据线丢了也没关系,只要有type-c转接口,一样可以用Micro USB充电/连接电脑

类适配器

1.首先定义M4DataLine 代表是Micro USB,我们目的就是通过适配器能够用米4数据线连接米5手机

class M4DataLine {
    public void connection() {
        System.out.println("使用小米4数据线连接...");
    }
}

2.定义客户端使用的接口,与业务相关

interface Target {
    void connection();
}

class M5DataLine implements Target {
    @Override
    public void connection() {
        System.out.println("使用小米5数据线连接...");
    }
}

3.创建适配器类,继承了被适配类,同时实现标准接口

class M5DataLineAdapter extends M4DataLine implements Target {

    @Override
    public void connection() {
        System.out.println("插入 type-c 转接头");
        super.connection();
    }
}

4.客户端代码,测试

public class AdapterMain {

    public static void main(String[] args) {
        Target target = new M5DataLine();
        target.connection();

        Target adapter = new M5DataLineAdapter();
        adapter.connection();
    }
}

5.结果

使用小米5数据线连接...
插入 type-c 转接头
使用小米4数据线连接...

对象适配器
创建适配器类,实现标准接口,将这个调用委托给实现新接口的对象来处理

class M5DataLineAdapter implements Target {

    private Target target;

    public M5DataLineAdapter(Target target) {
        this.target = target;
    }

    @Override
    public void connection() {
        System.out.println("插入 type-c 转接头");
        target.connection();
    }
}

public class AdapterMain {

    public static void main(String[] args) {
        // 使用特殊功能类,即适配类
        Target adapter = new M5DataLineAdapter(new M5DataLine());
        adapter.connection();
    }
}

区别:

类适配器:对象继承的方式,静态的定义。
对象适配器:依赖于对象的组合,都是采用对象组合的方式,也就是对象适配器实现的方式。

4.应用场景

JDK 中的适配器使用

使用适配器模式的类
java.util.Arrays#asList()
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)

  • Java I/O 库大量使用了适配器模式,如 ByteArrayInputStream 是一个适配器类,它继承了 InputStream 的接口,并且封装了一个 byte 数组。换言之,它将一个 byte 数组的接口适配成 InputStream 流处理器的接口。

  • 在 OutputStream 类型中,所有的原始流处理器都是适配器类。ByteArrayOutputStream 继承了 OutputStream 类型,同时持有一个对 byte 数组的引用。它一个 byte 数组的接口适配成 OutputString 类型的接口,因此也是一个对象形式的适配器模式的应用。

  • FileOutputStream 继承了 OutputStream 类型,同时持有一个对 FileDiscriptor 对象的引用。这是一个将 FileDiscriptor 接口适配成 OutputStream 接口形式的对象型适配器模式。

  • Reader 类型的原始流处理器都是适配器模式的应用。StringReader 是一个适配器类,StringReader 类继承了 Reader 类型,持有一个对 String 对象的引用。它将 String 的接口适配成 Reader 类型的接口。

Spring 中使用适配器模式的典型应用

  • 在 Spring 的 AOP 里通过使用的 Advice(通知)来增强被代理类的功能。Spring 实现这一 AOP 功能的原理就使用代理模式(1、JDK 动态代理。2、CGLib 字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类,并在代理类的方法前,设置拦截器,通过执行拦截器中的内容增强了代理方法的功能,实现的面向切面编程。

  • Advice(通知)的类型有:BeforeAdvice、AfterReturningAdvice、ThrowSadvice 等。每个 Advice(通知)类型都有对应的拦截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。Spring 需要将每个 Advice(通知)都封装成对应的拦截器类型,返回给容器,所以需要使用适配器模式对 Advice 进行转换。

你可能感兴趣的:(从《大话设计模式》看JDK及框架中常用的设计模式(三))