写点什么

装饰器模式

用户头像
Geek_571bdf
关注
发布于: 1 小时前

1. 装饰器与普通组合有什么区别?

2. 装饰器模式的作用

3. 如何实现装饰器模式?

4. 装饰器在 IO 流中的应用:FilterInputStream、InputStream


1. 装饰器模式的作用。

装饰器模式允许在不改变已有对象的结构下,向已有对象添加新功能。满足开闭原则,也不破坏现有的操作。

 

装饰器模式的典型应用是 IO 包。

InputStream in = new FileInputStream("/user/wangzheng/test.txt");InputStream bin = new BufferedInputStream(in);// 附加读写的缓存功能byte[] data = new byte[128];while (bin.read(data) != -1) {  //...}
复制代码

装饰器模式是通过组合来实现附加需求的。而非用继承。原因在于组合爆炸。当 n 个功能和 m 个类组合时,将有 n*m 个新类,将不可维护。

 

但装饰器模式与简单的组合有两对不同:

①装饰器类和原始类继承同样的父类,这样我们可以对原始类“嵌套”多个装饰器类。

// 既支持缓存读取,又支持按照基本数据类型来读取数据InputStream in = new FileInputStream("/user/wangzheng/test.txt");InputStream bin = new BufferedInputStream(in);DataInputStream din = new DataInputStream(bin);int data = din.readInt();
复制代码

②装饰器类是对功能的增强。装饰器模式与代理模式代码结构类似,但目的不同,代理类附加的是跟原始类无关的功能,而装饰器类附加的是跟原始类相关的增强功能。

 

2. 装饰器模式的实现。

// 装饰器模式的代码结构(下面的接口也可以替换成抽象类)public interface IA {  void f();}public class A impelements IA {  public void f() { //... }}public class ADecorator impements IA {  private IA a; // 基于组合  public ADecorator(IA a) {    this.a = a;  }    public void f() {    // 功能增强代码    a.f();    // 功能增强代码  }}
复制代码

3. FilterInputStream

IO 包中,类似 BufferedInputStream、DataInputStream 这样的装饰器类,并不直接继承自 InputStream,而是继承 FilterInputStream。

InputStream 是一个抽象类,大部分方法都有默认实现。按理说,BufferedInputStream 只需要重写需要增强的功能方法即可。但实际上,对于即便是不需要增加缓存功能的方法,BufferedInputStream 还是必须把它重新实现一遍,简单包裹对 InputStream 对象的函数调用。

原因在于,只有具体的 InputStream 类才有真正的 IO 功能,比如 FileInputStream。如果不重写,调用的是 InputStream 的方法,它不具有真正的 IO 功能。装饰器类都有类似的问题,为了避免编写重复的代码,Java IO 抽象出了一个装饰器父类 FilterInputStream。

public class FilterInputStream extends InputStream {  protected volatile InputStream in;  protected FilterInputStream(InputStream in) {    this.in = in;  }
public int read() throws IOException {// FilterInputStream将InputStream的方法都做了如下这样类似的包装 return in.read(); } public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
复制代码


用户头像

Geek_571bdf

关注

还未添加个人签名 2019.06.13 加入

还未添加个人简介

评论

发布
暂无评论
装饰器模式