设计模式之适配器模式

adapter design pattern

适配模式的概念、适配模式的结构、适配模式的优缺点、适配模式的使用场景、适配模式的实现示例(类适配模式和对象适配模式)、适配模式的源码分析


1、适配模式的概念

  适配器模式,即将一个类的某个接口转换成用户希望的另一个接口,使得原本由于接口不兼容而不能在一起工作的类可以在一起工作。适配器模式分为类适配器模式和对象适配器模式,类适配器模式依赖继承关系实现,故比依赖组合或聚合关系实现的对象适配器模式耦合度高。

2、适配模式的结构

  • 抽象原有接口:即用户最终要访问的接口,定义原有接口的行为。
  • 具体原有接口:实现抽象原有接口,实现原有接口的具体行为。
  • 抽象目标接口:即用户要求的接口,定义用户目标接口的行为。
  • 适配器:实现抽象目标接口,实现目标接口的行为。

adapter-class

3、适配模式的优缺点

  • 优点:
    • 用户可以透明的调用目标接口(这里的目标接口指原有接口)。
    • 复用了现有的组件,即无需修改已有的组件即可实现用户对目标接口的调用。
  • 缺点:
    • 对适配器来说,更换适配器较复杂。
    • 在类适配模式中,依赖继承关系实现,且目标类必须抽象。

4、适配模式的使用场景

  • 系统需要使用现有的类,但现有类的接口不符合系统的需要。
  • 想建立一个可以重复使用的类,用于一些彼此之间没有太大关联的类。
  • 通过接口转换,将一个类嵌入到另一个类中。

5、适配模式的实现示例

5.1、类适配模式的实现示例

抽象原有接口:

public interface Original {

    /**
     * 定义原有类行为
     * @param name
     */
    void behavior(String name);
}

具体原有接口:

public class SpecificOriginal implements Original {

    @Override
    public void behavior(String name) {
        System.out.println("我是具体原有对象 " + name);
    }
}

抽象目标接口:

public interface Target {

    /**
     * 定义目标类行为
     */
    void behavior();
}

适配器:

public class Adapter extends SpecificOriginal implements Target {

    @Override
    public void behavior() {
        System.out.println("我是适配器对象");
        this.behavior("momo");
    }
}

测试:

public class ClassAdapterTest {

    public static void main(String[] args) {
        Target adapter = new Adapter();
        adapter.behavior();
    }
}

测试结果:

我是适配器对象
我是具体原有对象 momo
5.2、对象适配模式的实现示例

抽象原有接口:

public interface Original {

    /**
     * 定义原有类行为
     * @param name
     */
    void behavior(String name);
}

具体原有接口:

public class SpecificOriginal implements Original {

    @Override
    public void behavior(String name) {
        System.out.println("我是具体原有对象 " + name);
    }
}

抽象目标接口:

public interface Target {

    /**
     * 定义目标类行为
     */
    void behavior();
}

适配器:

public class Adapter implements Target {

    private Original original;

    public Adapter(Original original) {
        this.original = original;
    }

    @Override
    public void behavior() {
        System.out.println("我是适配器对象");
        this.original.behavior("momo");
    }
}

测试:

public class ObjectAdapterTest {

    public static void main(String[] args) {
        Target adapter = new Adapter(new SpecificOriginal());
        adapter.behavior();
    }
}

测试结果:

我是适配器对象
我是具体原有对象 momo

6、适配模式的源码分析

  jdk 中的 Reader(字符流)、InputStream(字节流)的适配使用的是 InputStreamReader。InputStreamReader 继承自 java.io 包中的 Reader,实现了其抽象未实现的方法,如下:

public class InputStreamReader extends Reader {
  
  private final StreamDecoder sd;
  
      /**
     * Reads a single character.
     *
     * @return The character read, or -1 if the end of the stream has been
     *         reached
     *
     * @exception  IOException  If an I/O error occurs
     */
    public int read() throws IOException {
        return sd.read();
    }

    /**
     * Reads characters into a portion of an array.
     *
     * @param      cbuf     Destination buffer
     * @param      offset   Offset at which to start storing characters
     * @param      length   Maximum number of characters to read
     *
     * @return     The number of characters read, or -1 if the end of the
     *             stream has been reached
     *
     * @exception  IOException  If an I/O error occurs
     * @exception  IndexOutOfBoundsException {@inheritDoc}
     */
    public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length);
    }
  ...
}
public class StreamDecoder extends Reader {
  ...
}

  从源码可以看出,InputStreamReader 是对同样实现了 Reader 的 StreamReader 的 的封装,所以从表面看是 InputStreamReader 做了 InputStream 字节流到 Reader 字符流的转换,实际上其是调用了 StreamDecoder 的实现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值