一、定义
GOF上对装饰器模式的意图这样描述:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式比生成子类更为灵活。从根本来说,装饰器模式将多态和委托结合在一起,使得我们可以动态地组合对象的行为。
二、场景设计
装饰器模式的典型应用是Java里的流设计。在java中,通常每个流对象中包含另一个流对象,一个流对象通常会将自己预先处理过的字符或比特流转发给里层的另一个流对象。通常情况下,在装饰器模式中,类的实现依赖于作为构造方法参数的那个装饰器的对象。一个例子,GZIPOutputStream类实现write()操作的方法是:压缩接收到的比特,然后把他们写到作为构造方法参数传入的OutputStream对象中去。换句话说,GZIPOutputStream类在OutputStream对象的基础上添加了压缩操作。
三、类图
回到Java流的例子上来,在字节输出流OutputStream的类体系中,虚基类OutputStream提供write的接口和基本实现。其子类FilterOutputStream继承了它,并且组合了一个OutputStream的对象句柄。这个类相当于上图的Decorator类。
BufferedOutputStream、PrintStream和DataOutputStream则继承了FilterOutputStream,他们在原有的输出基础上,加上了缓冲区,格式化输出,向比特流中写入基本类型数据等功能,这些类相当于图中的ConcreteDecorator类。
而FileOutputStream、ByteArrayOutputSteam则直接继承OutputStream接口,用于进行直接输出。这些类相当于上图中的ConcreteComponent类。
每个装饰器的构造方法都需要一个OutputStream类对象作为参数,这其实是一种递归思想。而FileOutputStream这些类则是递归的出口。同时,由于装饰器都有一个公共的OutputStream父类,各个装饰器对象在实例化时,可以互相作为彼此的构造参数。这样就达到了组合多个装饰器功能的效果了。
四、代码示例
OozinozFilter.java 装饰器类
import java.io.*;
public class OozinozFilter extends Writer {
Writer out;
protected OozinozFilter(Writer out) {
super(out);
this.out=out;
}
public void write(char[] cbuf,int off,int len) throws IOException
{
out.write(cbuf, off, len);
}
public void write(int c) throws IOException {
out.write(c);
}
public void write(String str,int off,int len) throws IOException
{
out.write(str, off, len);
}
@Override
public void flush() throws IOException {
// TODO Auto-generated method stub
out.flush();
}
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
out.close();
}
}
RandomCaseFilter.java 装饰器类,对输入的字符串随机生成字母大小写的版本
import java.io.*;
import java.util.Random;
public class RandomCaseFilter extends OozinozFilter{
Random rand=null;
char[] temp=null;
protected RandomCaseFilter(Writer out) {
super(out);
// TODO Auto-generated constructor stub
rand=new Random();
}
public void write(int c)throws IOException
{
int flag=rand.nextInt(2);
out.write(flag==0?Character.toLowerCase((char)c):Character.toUpperCase((char)c));
}
public void write(char[] buf,int off,int len) throws IOException{
for(int i=off;i<len;i++)
write(buf[i]);
}
public void write(String buf,int off,int len) throws IOException{
temp=buf.toCharArray();
for(int i=off;i<len;i++)
write(temp[i]);
}
}
Main.java
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Main {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
FileWriter fw=new FileWriter(new File("out"));
OozinozFilter of=new OozinozFilter(fw);
RandomCaseFilter rf=new RandomCaseFilter(of);
rf.write("helloWorld", 0, 10);
rf.close();
}
}
输出结果:HElLOwOrLd
装饰器模式是一种设计模式,能动态地给对象添加新的职责,比生成子类更加灵活。在Java流设计中广泛应用,如GZIPOutputStream通过装饰器增加了压缩功能。类图展示了装饰器如何通过递归构造实现功能组合,如BufferedOutputStream增加了缓冲功能。代码示例展示了装饰器的实际应用。

1093

被折叠的 条评论
为什么被折叠?



