作者:Grey
原文地址:
博客园:设计模式学习(九):装饰器模式
CSDN:设计模式学习(九):装饰器模式
装饰器模式是一种结构型模式。
顾名思义,就是对某个方法或者对象进行装饰,举个简单的例子,有个圆形类 Circle,我需要把这个圆形的涂上红色,其实就是新增一个装饰器来装饰这个圆形类。
如果要让装饰器通用一些,可以处理圆形类对应的抽象类 Sharp ,那么对于任意 Sharp 的子类,都可以用红色装饰器来涂红色。
示例代码如下
我们先定义 Sharp 这个抽象类
public abstract class Sharp {protected abstract void draw();
}
然后我们定义 Sharp 的装饰类 SharpDecorator ,这个类是所有装饰器类的抽象类,后续的装饰器只需要实现这个抽象类就可以对 Sharp 进行各种装饰了,
public abstract class SharpDecorator extends Sharp {protected Sharp decoratedSharp;public SharpDecorator(Sharp decoratedSharp) {this.decoratedSharp = decoratedSharp;}
}
红色装饰器实现这个抽象类即可:
public class RedSharpDecorator extends SharpDecorator {public RedSharpDecorator(Sharp decoratedSharp) {super(decoratedSharp);}private static void redIt() {System.out.println("[RED]");}@Overrideprotected void draw() {redIt();this.decoratedSharp.draw();redIt();}
}
主方法调用的时候只需要:
new RedSharpDecorator(new Circle()).draw();
UML 图如下:
说明:
装饰器类和原始类继承同样的父类,这样我们可以对原始类“嵌套”多个装饰器类。
装饰器类是对功能的增强,这也是装饰器模式应用场景的一个重要特点。符合“组合关系”这种代码结构的设计模式有很多,比如代理模式、桥接模式,还有现在的装饰器模式。尽管它们的代码结构很相似,但是每种设计模式的意图是不同的。就拿比较相似的代理模式和装饰器模式来说:
代理模式中,代理类附加的是跟原始类无关的功能;
装饰器模式中,装饰器类附加的是跟原始类相关的增强功能。
在 JDK 中,BufferedInputStream 、 DataInputStream 并非继承自 InputStream ,而是另外一个叫 FilterInputStream 的类。
这是因为 InputStream 是一个抽象类而非接口,而且它的大部分函数(比如 read()
、available()
)都有默认实现,按理来说,我们只需要在 BufferedInputStream 类中重新实现那些需要增加缓存功能的函数就可以了,其他函数只需要复用 InputStream 的默认实现。但实际上,这样做是行不通的。对于即便是不需要增加缓存功能的函数来说,BufferedInputStream 还是必须把它重新实现一遍,简单包裹对 InputStream 对象的函数调用。那 BufferedInputStream 类就无法将最终读取数据的任务,委托给传递进来的 InputStream 对象来完成,DataInputStream 也存在跟 BufferedInputStream 同样的问题。为了避免代码重复,Java I/O 包中抽象出了一个装饰器父类 FilterInputStream,包装了 InputStream 的默认实现
package java.io;public class FilterInputStream extends InputStream {protected volatile InputStream in;protected FilterInputStream(InputStream in) {this.in = in;}public int read() throws IOException {return in.read();}public int read(byte b[]) throws IOException {return read(b, 0, b.length);}public int read(byte b[], int off, int len) throws IOException {return in.read(b, off, len);}public long skip(long n) throws IOException {return in.skip(n);}public int available() throws IOException {return in.available();}public void close() throws IOException {in.close();}public synchronized void mark(int readlimit) {in.mark(readlimit);}public synchronized void reset() throws IOException {in.reset();}public boolean markSupported() {return in.markSupported();}
}
InputStream 的所有的装饰器类( BufferedInputStream 和 DataInputStream )都继承自这个装饰器父类。这样,装饰器类只需要实现它需要增强的方法就可以了,其他方法继承装饰器父类的默认实现。
其他应用
Java 中的 I/O 流, Read/InputStream
,Write/OutputStream
;
Java 中的 UnmodifiableCollection
;
Spring 中的 HttpHeadResponseDecorator
, 还有对 Cache 的装饰类 TransactionAwareCacheDecorator
。
UML 图
代码
设计模式学习专栏
Effective Java中文版(第3版)
Head First 设计模式
设计模式-可复用面向对象软件的基础
坦克大战-马士兵
菜鸟教程-设计模式
极客时间-设计模式之美-王争