设计模式 -- 适配器模式

将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式分为类适配器模式和对象适配器模式。前者类之间的耦合度比后者高,并且要求程序员了解现有组件库中相关组件的内部结构。所以应用的相对少点。

结构:

目标接口(Target):当前系统业务所期望的接口,它可以是抽象类或者接口。【客户提供】

适配者类(Adaptee):它是被访问和适配的现存组件库中的组件接口。【系统现有】

适配器类(Adapter):它是一个转换器,通过继承或者引用适配者对象,把适配者接口转换成目标接口,让客户按照目标接口的格式访问适配者。【转接口】

类适配器模式:

定义一个适配器类来实现当前业务的接口,同时又继承现有组件库中已存在的组件。

【例】现有一台电脑只能读取SD卡,而现在需要读取一张TF卡中的内容。相比于换电脑,转接口更符合实际。所以在这个模式下用到了适配器模式。创建一个读卡器类,将TF卡中内容读取出来。

/**
 * 适配器模式 类适配器模式
 * 适配者接口 【定义格式】
 * TF卡
 */
public interface TFCard {

    /**
     * 从TF卡中读取数据
     * @return TF卡中现存数据
     */
    String readTF();

    /**
     * 往TF卡写入数据
     * @param msg 待写入
     */
    void writeTF(String msg);
}


/**
 * 适配器模式 类适配器模式
 * 适配者类
 * 【我们需要将卡中数据在电脑上被读取和写入。所以这里是适配者
    电脑提供的接口是目标接口,也是客户期望的接口】
 * 具体的那张 TF卡
 */
public class TFCardImpl implements TFCard{


    @Override
    public String readTF() {
        String msg = "TF卡 读取信息: hello world";
        return msg;
    }

    @Override
    public void writeTF(String msg) {
        System.out.println("TF卡 写入信息:" + msg);
    }
}
/**
 * 适配器模式 类适配器模式
 * 目标接口 【定义格式】
 * SD卡
 */
public interface SDCard {

    /**
     * 从SD卡中读取数据
     * @return TF卡中现存数据
     */
    String readSD();

    /**
     * 往SD卡写入数据
     * @param msg 待写入
     */
    void writeSD(String msg);
}

/**
 * 适配器模式 类适配器模式
 * 目标接口类
 * 【这里是电脑本身的接口,也就是客户本身提供的接口,所以这里对于程序员来说是目标接口类】
 * 具体的那张 SD卡
 */
public class SDCardImpl implements SDCard {

    @Override
    public String readSD() {
        String msg = "SD卡 读取信息: hello world";
        return msg;
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("SD卡 写入信息:" + msg);
    }
}
/**
 * 适配器模式 类适配器模式
 * 客户端类
 * 只能读取SD卡信息的电脑
 */
public class Computer {

    /**
     * 读取SD卡
     * @param sdCard 需要一张SD卡
     * @return sd卡的内容
     */
    public String readSD(SDCard sdCard){
        if (sdCard == null){
            throw new NullPointerException("SD卡不能为空");
        }
        return sdCard.readSD();
    }
}
/**
 * 适配器模式 类适配器模式
 * 适配器类
 * 转接口 SD - TF 适配器
 */
public class Adapter extends TFCardImpl implements SDCard {


    @Override
    public String readSD() {
        System.out.println("适配器生效 ---> 读取TF卡中的数据");
        return readTF();
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("适配器生效 ---> 往TF卡中写入数据" + msg);
        writeTF(msg);
    }
}

类适配器模式违背了合成复用原则。假如有多个适配者类,java并不支持多继承。

对象适配器模式:

定义一个适配器类来实现当前业务的接口,同时又引入现有组件库中已存在的组件。

这样不仅修复了类适配器模式的合成复用原则的缺陷,也可以不强制客户端提供接口。

其他功能不变,只需要改动适配器即可

/**
 * 适配器模式 对象适配器模式
 * 适配器类
 * 转接口 SD - TF 适配器
 */
public class AdapterNew implements SDCard {

    //聚合TFCard 接口而非继承
    private TFCard tfCard;

    //声明有参构造函数获取实际的 tfCard
    public AdapterNew(TFCard tfCard){
        this.tfCard = tfCard;
    }

    @Override
    public String readSD() {
        System.out.println("适配器生效 ---> 读取TF卡中的数据");
        return tfCard.readTF();
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("适配器生效 ---> 往TF卡中写入数据" + msg);
        tfCard.writeTF(msg);
    }
}

使用场景:

以前开发的老系统存在满足新新系统功能需求的类,但是其接口不一致

使用第三方组件库,但是对方提供的接口和我们自己拟定的接口定义不同

JDK源码分析:

Reader【字符输入流】、InputStream【字节输入流】的适配使用的是 InputStreamReader

InputStreamReader 继承自java.io包中的reader,对它的未实现抽象方法给出了具体实现。

可以将字节流转换为字符流。

其中的sd 【StreamDecoder对象,解码对象。将字节流转成字符流】,Sun在JDK的实现中,实际是对 sun.nio.cs.StreamDecoder对象的引用

在上面的关系网中使用了适配器模式,StreamDecoder是Sun公司的具体实现,它是一个标准的适配器。它实现了字符流对字节流的转换,实现是同一个read接口,但是做了不一样的数据返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值