设计模式-装饰者模式
上一篇说到适配器模式,这次说它的同胞兄弟——装饰器模式。我们有时会遇到需要对类自身方法功能的累加,比如 FilterInputStream
需要 InputStream
其他子类的read
上累加功能。
举例
装饰器通常需要一个源,即你认为需要包装或基于此添加功能的类,源需要与装饰器同父类。
如下代码,源 DecoratorTargetSource
被实例化时并不需要传入任何 DecoratorTarget
类型,而 Decorator1
、Decorator2
、Decorator3
等装饰类实例化时需要 DecoratorTarget
类型对象。
//基类(接口)
public interface DecoratorTarget {
void read(byte[] bs);
}
//源基类
public class DecoratorTargetSource implements DecoratorTarget {
@Override
public void read(byte[] bs) {}
}
//源基类装饰器1
public class Decorator1 implements DecoratorTarget {
protected DecoratorTarget target;
public Decorator1(DecoratorTarget target) {
this.target = target;
}
@Override
public void read(byte[] bs) {
// ...
target.read(bs);
// ...
}
}
//源基类装饰器2
public class Decorator2 implements DecoratorTarget {
protected DecoratorTarget target;
public Decorator2(DecoratorTarget target) {
this.target = target;
}
@Override
public void read(byte[] bs) {
// ...
target.read(bs);
// ...
}
}
//源基类装饰器3
public class Decorator3 extends Decorator1 {
public Decorator3(DecoratorTarget target) {
super(target);
this.target = target;
}
@Override
public void read(byte[] bs) {
// ...
target.read(bs);
// ...
}
}
public class DecoratorTemplate {
public static void main(String[] args) {
DecoratorTarget target = new Decorator1(new Decorator3(new Decorator2(new DecoratorTargetSource())));
}
}
JDK 中的装饰器模式
Java 中最为人所知的装饰器模式,莫过于 IO 框架。源码如下:
//基类
public abstract class InputStream implements Closeable {
//...
}
//装饰器FilterInputStream
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
}
//装饰器BufferedInputStream,继承于FilterInputStream
public class BufferedInputStream extends FilterInputStream {
private InputStream getInIfOpen() throws IOException {
InputStream input = in;
if (input == null)
throw new IOException("Stream closed");
return input;
}
private void fill() throws IOException {
// ...
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
// ...
}
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
}
//源
public class FileInputStream extends InputStream {
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.incrementAndGetUseCount();
this.path = name;
open(name);
}
public FileInputStream(FileDescriptor fdObj) {
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
path = null;
fd.incrementAndGetUseCount();
}
}
上述源码中,FileInputStream
并没有参数包含 InputStream
类型,所以可以看成是一个源,那么 FilterInputStream
及其子类 BufferedInputStream
则是装饰器。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: 设计模式-适配器模式
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论