文章目录
概念
定义:装饰器模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案(具有动态性,因为继承是继承指定类,在编译时就确定了。而组合可以动态的选择拓展哪个类)
应用场景
就是在一个类的外面包了一层。具体点,就是在调用一个类的方法之前或之后,添加功能。
我们看一下《headFirst 设计模式》中的 星巴兹的例子:
看见没有,Mocha、Milk中有一个实例变量Beverage
。
- 为什么需要继承
CondimentDecorator
?
就是为了让getDescription()变成一个抽象方法,好强制让具体的装饰器类实现。其实这个类不需要也行,这就继承自Beverage
。 - 为什么需要继承
Beverage
类呢?
是为了获取行为(如cost
行为),而不是为了获取实例变量。
下面是截自《HeadFirst设计模式》中的图,表示一杯添加得有Mocha和Whip调料的BarkRoast。
注意:Whip调料类、BarkRoast基本饮料类我没添加到上面类图中。
jdk源码中装饰模式的应用
jdk源码中用到装饰模式的地方:java I/O
下面是类图:
InputStream抽象类:
/* This abstract class is the superclass of all classes representing
* an input stream of bytes.
*/
abstract class InputStream implements Closeable {
// MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
// use when skipping.
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
/**
* Reads the next byte of data from the input stream.
*/
public abstract int read() throws IOException;
/**
* Reads some number of bytes from the input stream and stores them into
* the buffer array .
* */
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* Reads up to <code>len</code> bytes of data from the input stream into
* an array of bytes.
*/
public int read(byte b[], int off, int len) throws IOException {
//do stuff
}
/**
* Skips over and discards <code>n</code> bytes of data from this input
* stream.
*/
public long skip(long n) throws IOException {
//do stuff
}
/**
* Returns an estimate of the number of bytes that can be read (or
* skipped over) from this input stream without blocking by the next
* invocation of a method for this input stream.
*/
public int available() throws IOException {
return 0;
}
/**
* Closes this input stream and releases any system resources associated
* with the stream.
*/
public void close() throws IOException {
}
/**
* Marks the current position in this input stream.
*/
public synchronized void mark(int readlimit) {
}
/**
* Repositions this stream to the position at the time the
* <code>mark</code> method was last called on this input stream.
*/
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
/**
* Tests if this input stream supports the <code>mark</code> and
* <code>reset</code> methods.
*/
public boolean markSupported() {
return false;
}
}
然后是FilterInputStream.java
FilterInputStream extends InputStream {
/**
* 由于每个具体的装饰器类都需要传入一个被装饰类的抽象类,所以直接提到这里。
*/
protected volatile InputStream in;
/**
*由于每个具体的装饰器类的构造函数都需要传入一个InputStream,所以直接将这段提出到这里
*/
protected FilterInputStream(InputStream in) {
this.in = in;
}