装饰模式
装饰模式能够灵活的对对象的功能进行拓展,而不需要创建更多的类。
话不多说直接上uml图
包括抽象构建角色(Component),具体构件角色(Concrete Component),装饰角色(Decorator 重点),具体装饰角色(Concrete Decorator)。先暂且对这些有个大概的印象。
下面直接通过一个典型的示例来说明具体如何定义和使用
没错Java的IO类就是一个典型的应用 下面我们对照UML图实现一个简化版的inputstream
/**
* 抽象构建角色(Component)
*/
public abstract class InputStream {
/**
* 模拟inputstream的读取方法
*/
public abstract void read();
}
我们这里就实现FileInputStream这个具体构件角色,ByteArrayInputStream和StringBufferInputStream同理就不列出来了
/**
* 被装饰的具体对象
*/
public class FileInputStream extends InputStream {
@Override
public void read() {
System.out.println("FileInputStream read");
}
}
接下来就到重点了装饰角色和具体装饰角色 ,装饰角色持有inputstream的引用(重点注意一下,后面会提到)
/**
* 装饰角色
*/
public class FilterInputStream extends InputStream {
//被装饰的对象随便用来装饰啥都行
private InputStream inputStream;
//和代理模式区别在于这里传递的是一个接口
public FilterInputStream(InputStream inputStream){
this.inputStream = inputStream;
}
@Override
public void read() {
this.inputStream.read();
}
}
具体装饰角色:重点看到构造函数的super(inputstream)和super.read(),这是能够实现装饰功能的关键。
/**
* 具体装饰角色
*/
public class BufferedInputStream extends FilterInputStream {
public BufferedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public void read() {
super.read();
System.out.println("BufferedInputStream decorate");
}
}
/**
* 具体装饰角色
*/
public class DataInputStream extends FilterInputStream {
public DataInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public void read() {
super.read();
System.out.println("DataInputStream decorate");
}
}
/**
* 具体装饰角色
*/
public class LineNumberInputStream extends FilterInputStream {
public LineNumberInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public void read() {
super.read();
System.out.println("LineNumberInputStream decorate");
}
}
下面我们写个方法运行一下看一下效果
public class Client {
public static void main(String[] args) {
//被装饰对象
InputStream inputStream = new FileInputStream();
//然后被各种装饰
InputStream bufferedInputStream = new BufferedInputStream(inputStream);
InputStream dataInputStream = new DataInputStream(new LineNumberInputStream(bufferedInputStream));
dataInputStream.read();
}
}
输出结果:
FileInputStream read
BufferedInputStream decorate
LineNumberInputStream decorate
DataInputStream decorate
可以看到已经成功实现了装饰的功能,调用的依旧还是read方法却已经加上了各种功能