装饰者模式是要解决什么问题?
官方说法:装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
个人理解:原始接口功能不足,需要添加新方法,但是别的地方已经实现了原始接口,所以原始接口又不能直接添加方法。这时候可以采用持有原始类对象,并且添加新方法的方式,实现新功能。并且继承原始类或者实现原始接口,达到可替换原始类的目的。
装饰者模式在JDK中有哪些实际应用?
FilterInputStream
InputStream是一个抽象类,源码:
public abstract class InputStream implements Closeable {
...
public abstract int read() throws IOException;
...
}
InputFilterStream源码:
public
class FilterInputStream extends InputStream {
protected volatile InputStream in;
...
public int read() throws IOException {
return in.read();
}
...
}
BufferedInputStream源码:
public
class BufferedInputStream extends FilterInputStream {
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
public BufferedInputStream(InputStream in, int size) {
super(in); //注意这里调用了FilterInputStream的构造器
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
...
private InputStream getInIfOpen() throws IOException {
InputStream input = in;
if (input == null)
throw new IOException("Stream closed");
return input;
}
...
}
三个类完整的方法:
InputStream是抽象类,且只有一个抽象方法。
FilterInputStream并没有增加方法,只是持有了InputStream的实例。
BufferedInputStream增加了几个方法,例如:getInIfOpen()
。
使用BufferedInputStream:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("/home/user/abc.txt")));
装饰者模式在Android SDK中有哪些实际应用?
- ContextWrapper与Application、Activity。具体参考:设计模式(十一)Context中的装饰者模式
网上有些博客讲用装饰者模式给RecyclerView添加Header。例如:装饰者设计模式-RecyclerView添加头部和底部 ,我没有仔细分析,不下结论。
装饰者模式和适配器模式的区别是什么?
简单讲:装饰者模式解决的是原始类功能不足的问题。适配器模式解决的是原始类有这个功能,但是功能不匹配的问题。
例如原始类有裤子,但是没有鞋子,这个时候用装饰器模式。原始类有鞋子,但是鞋码大了,不合适,这个时候用适配器模式。
装饰者模式:
- 装饰者模式(Decorator Pattern)目的是为原始类对象动态地添加新功能。解决原始类功能不足的问题。
- 装饰者类起功能增强作用。
- 继承原有类,创建一个装饰器类,将原始类对象包装在装饰器中,以组合的方式来添加功能。
适配器模式:
- 适配器模式(Adapter Pattern)目的是为了实现目标接口,解决原始类功能不匹配的问题。使目标接口和原始类进行交互。
- 适配器类起一个桥梁的作用。
- 适配器模式通过创建一个适配器类,配合原始类的方法,实现目标接口的方法。
装饰者模式和代理模式的区别是什么?
- 目的不同:装饰者模式是为了扩展原有对象的功能,在装饰者中添加新的方法。代理模式是为了控制原有对象的访问,在原有对象的方法上做了修改。
- 方法数量不同:装饰者模式中,装饰者的方法数量比被装饰者多,因为要添加新的方法。代理模式一般情况下方法数量和父类相同。
- 原有对象访问修饰符不同:装饰者模式中,原有对象的访问修饰符一般是
protected