设计模式之适配器模式、IO流中的适配器

9 篇文章 0 订阅
2 篇文章 0 订阅

适配器介绍

Adapter:将一个类的接口转化成客户希望的另外的一个接口,乍一听十分弱智,你直接调用希望的那一个接口不就完了??

Adapter模式使原来接口不兼容,不能一起工作的类可以一起工作。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

实现:类适配器和对象适配器

  • 使用继承(就是所谓的类适配器模式)
  • 使用组合(就是所谓的对象适配器模式)

适配器所涉及的角色有:

  • Target(目标接口):所要转换的所期待的接口(笔记本电脑USB插口)
  • Adaptee(源角色):需要适配的类(内存卡)
  • Adapter(适配器):将源角色适配成目标接口,一般持有源接口的引用(或者继承源接口),且实现目标接口(读卡器)
  • Client(客户类):通过目标角色获取服务(笔记本电脑)

优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。

缺点: 1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 2、由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

示例代码

类适配器

电子产品的接口有TypeC插口和USB插口,我们现在将USB接口适配成TypeC插口,让只有TypeC插口的电子产品也可以使用USB插口

Adaptee:USB插口

/**
 * Adaptee
 * 存在一个USB插口
 * 该插口已经实现其特定的USB插口的功能
 */
public class USB {
    void isUSB() {
        System.out.println("USB插口...");
    }
}

Target:TypeC插口

/**
 * Target
 * TpyeC接口
 * 即需要的目标接口
 */
public interface TypeC {
    public void isTypeC();
}

Adapter:类适配器要继承正在使用的功能的类,并且实现想要转换的功能的接口

/**
 * Adapter
 * 类适配器
 * 核心类:将USB适配成TypeC
 */
public class ClassAdapter extends USB implements TypeC {
    @Override
    public void isTypeC() {
        // TypeC接口的实现是通过适配USB来实现的
        super.isUSB();
    }
}

Client

public class Client {
    public static void main(String[] args) {
        // 类适配器的实现
        TypeC typeC = new ClassAdapter();
        // 通过typeC提供服务
        typeC.isTypeC();
    }
}

运行结果:可以看出:调用了isTypeC()方法打印的是USB的功能,实现了转换

对象适配器

我们有了上面的例子,只需要修改Adapter和Client即可,其余部分可保持不变。

Adapter:只需实现接口,实例是定义在类中的来调用之前的方法

public class ObjectAdapter implements TypeC {
    // 保存需要适配的类对象
    private USB usb;

    // 通过构造函数实例化需要适配的类的对象
    public ObjectAdapter(USB usb) {
        this.usb = usb;
    }

    @Override
    public void isTypeC() {
        usb.isUSB();
    }
}

Client:

public class Client {
    public static void main(String[] args) {
        TypeC typeC = new ObjectAdapter(new USB());
        typeC.isTypeC();
    }
}

运行结果:可以看出:调用了isTypeC()方法打印的是USB的功能,实现了转换

IO中的使用

适配器在IO中的使用:

  • 适配器角色就是InputStreamReader
  • 被适配的角色就是InputStream类的实例对象
  • 目标接口是Reader

目标类Reader操作字符:

public abstract class Reader implements Readable, Closeable
public int read(char[] cbuf)

需要适配的类InputStream操作字节:

public abstract class InputStream implements Closeable
public int read(byte[] b)

适配器类转换流InputStreamReader,InputStream是操作字节的

public class InputStreamReader extends Reader {
    private final StreamDecoder sd;

    public InputStreamReader(InputStream in) {
        super(in);

        try {
            this.sd = StreamDecoder.forInputStreamReader(in, this, (String)null);
        } catch (UnsupportedEncodingException var3) {
            throw new Error(var3);
        }
    }

构造函数传递字节流,StreamDecoder是一个解码类,将传进来的in字节解码成字符。

public int read(char[] cbuf, int offset, int length) throws IOException {
    return this.sd.read(cbuf, offset, length);
}

InputStreamReader的read操作内部调用的是sd的read操作,这个方法是操作字节的。

这就是一个典型的适配器使用的一个典范,IO中类似的适配器还有很多,处理流中有很多例子。

适配器这种设计模式主要就是各种角色的划分,要划分好角色之后进行编码实现。

装饰器与适配器异同点

  • 装饰器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的不相同
  • 适配器模式:是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的
  • 装饰器模式:不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能
  • 或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的
    器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的不相同
  • 适配器模式:是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的
  • 装饰器模式:不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能
  • 或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值