decorator模式:Java IO 包中的Decorator模式来源: 发布时间:星期五, 2008年12月19日 浏览:2次 评论:0
JDK为员提供了大量类库而为了保持类库可重用性可扩展性和灵活性其中使用到了大量设计模式本文将介绍JDKI/O包中使用到Decorator模式并运用此模式实现个新输出流类
Decorator模式介绍
Decorator模式又名包装器(Wrapper)它主要用途在于给个对象动态添加些额外职责和生成子类相比它更具有灵活性
有时候我们需要为个对象而不是整个类添加些新功能比如给个文本区添加个滚动条功能我们可以使用继承机制来实现这功能但是这种思路方法不够灵活我们无法控制文本区加滚动条方式和时机而且当文本区需要添加更多功能时比如边框等需要创建新类而当需要组合使用这些功能时无疑将会引起类爆炸
我们可以使用种更为灵活思路方法就是把文本区嵌入到滚动条中而这个滚动条类就相当于对文本区个装饰这个装饰(滚动条)必须和被装饰组件(文本区)继承自同个接口这样用户就不必关心装饰实现这对他们来说是透明装饰会将用户请求转发给相应组件(即相关思路方法)并可能在转发前后做些额外动作(如添加滚动条)通过这种思路方法我们可以根据组合对文本区嵌套区别装饰从而添加任意多功能这种动态对对象添加功能思路方法不会引起类爆炸也具有了更多灵活性
以上思路方法就是Decorator模式它通过给对象添加装饰来动态添加新功能如下是Decorator模式UML图:
Component为组件和装饰公共父类它定义了子类必须实现思路方法
ConcreteComponent是个具体组件类可以通过给它添加装饰来增加新功能
Decorator是所有装饰公共父类它定义了所有装饰必须实现思路方法同时它还保存了个对于Component引用以便将用户请求转发给Component并可能在转发请求前后执行些附加动作
ConcreteDecoratorA和ConcreteDecoratorB是具体装饰可以使用它们来装饰具体Component
Java IO包中Decorator模式
JDK提供java.io包中使用了Decorator模式来实现对各种输入输出流封装以下将以java.io.OutputStream及其子类为例讨论下Decorator模式在IO中使用
首先来看段用来创建IO流代码:
以下是代码片段:
try {
OutputStream out = DataOutputStream( FileOutputStream("test.txt"));
} catch (FileNotFoundException e) {
e.prStackTrace;
}
这段代码对于使用过JAVA输入输出流人来说再熟悉不过了我们使用DataOutputStream封装了个FileOutputStream这是个典型Decorator模式使用FileOutputStream相当于ComponentDataOutputStream就是个Decorator将代码改成如下将会更容易理解:
以下是代码片段:
try {
OutputStream out = FileOutputStream("test.txt");
out = DataOutputStream(out);
} catch(FileNotFoundException e) {
e.prStatckTrace;
}
由于FileOutputStream和DataOutputStream有公共父类OutputStream因此对对象装饰对于用户来说几乎是透明下面就来看看OutputStream及其子类是如何构成Decorator模式:
OutputStream是个抽象类它是所有输出流公共父类其源代码如下:
以下是代码片段:
public abstract OutputStream implements Closeable, Flushable {
public abstract void write( b) throws IOException;
...
}
它定义了write( b)抽象思路方法这相当于Decorator模式中Component类
ByteArrayOutputStreamFileOutputStream 和 PipedOutputStream 3个类都直接从OutputStream继承以ByteArrayOutputStream为例:
以下是代码片段:
public ByteArrayOutputStream extends OutputStream {
protected buf;
protected count;
public ByteArrayOutputStream {
this(32);
}
public ByteArrayOutputStream( size) {
(size 〈 0) {
throw IllegalArgumentException("Negative initial size: " + size);
}
buf = [size];
}
public synchronized void write( b) {
count = count + 1;
(count 〉 buf.length) {
buf = [Math.max(buf.length 〈〈 1, count)];
..gif' />copy(buf, 0, buf, 0, count);
buf = buf;
}
buf[count] = ()b;
count = count;
}
...
}
它实现了OutputStream中write( b)思路方法因此我们可以用来创建输出流对象并完成特定格式输出它相当于Decorator模式中ConcreteComponent类
接着来看下FilterOutputStream代码如下:
以下是代码片段:
public FilterOutputStream extends OutputStream {
protected OutputStream out;
public FilterOutputStream(OutputStream out) {
this.out = out;
}
public void write( b) throws IOException {
out.write(b);
}
...
}
同样它也是从OutputStream继承但是它构造很特别需要传递个OutputStream引用给它并且它将保存对此对象引用而如果没有具体OutputStream对象存在我们将无法创建FilterOutputStream由于out既可以是指向FilterOutputStream类型引用也可以是指向ByteArrayOutputStream等具体输出流类引用因此使用多层嵌套方式我们可以为ByteArrayOutputStream添加多种装饰这个FilterOutputStream类相当于Decorator模式中Decorator类它write( b)思路方法只是简单了传入流write( b)思路方法而没有做更多处理因此它本质上没有对流进行装饰所以继承它子类必须覆盖此思路方法以达到装饰目
BufferedOutputStream 和 DataOutputStream是FilterOutputStream两个子类它们相当于Decorator模式中ConcreteDecorator并对传入输出流做了区别装饰以BufferedOutputStream类为例:
以下是代码片段:
public BufferedOutputStream extends FilterOutputStream {
...
private void flushBuffer throws IOException {
(count 〉 0) {
out.write(buf, 0, count);
count = 0;
}
}
public synchronized void write( b) throws IOException {
(count 〉= buf.length) {
flushBuffer;
}
buf[count] = ()b;
}
...
}
这个类提供了个缓存Cache机制等到缓存Cache容量达到定字节数时才写入输出流首先它继承了FilterOutputStream并且覆盖了父类write( b)思路方法在输出流写出数据前都会检查缓存Cache是否已满如果未满则不写这样就实现了对输出流对象动态添加新功能目
下面将使用Decorator模式为IO写个新输出流
自己写个新输出流
了解了OutputStream及其子类结构原理后我们可以写个新输出流来添加新功能这部分中将给出个新输出流例子它将过滤待输出语句中空格符号比如需要输出"java io OutputStream"则过滤后输出为"javaioOutputStream"以下为SkipSpaceOutputStream类代码:
以下是代码片段:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* A output stream, which will check the space character
* and won’t write it to the output stream.
* @author Magic
*
*/
public SkipSpaceOutputStream extends FilterOutputStream {
public SkipSpaceOutputStream(OutputStream out) {
super(out);
}
/**
* Rewrite the method in the parent , and
* skip the space character.
*/
public void write( b) throws IOException{
(b!=’ ’){
super.write(b);
}
}
}
它从FilterOutputStream继承并且重写了它write( b)思路方法在write( b)思路方法中首先对输入进行了检查如果不是空格则输出
以下是个测试:
以下是代码片段:
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Test the SkipSpaceOutputStream.
* @author Magic
*
*/
public Test {
public void (String args){
buffer = [1024];
/**
* Create input stream from the standard input.
*/
InputStream in = BufferedInputStream( DataInputStream(.in));
/**
* write to the standard output.
*/
OutputStream out = SkipSpaceOutputStream( DataOutputStream(.out));
try {
.out.prln("Please input your words: ");
n = in.read(buffer,0,buffer.length);
for( i=0;i〈n;i){
out.write(buffer[i]);
}
} catch (IOException e) {
e.prStackTrace;
}
}
}
执行以上测试将要求用户在console窗口中输入信息将过滤掉信息中空格并将最后结果输出到console窗口比如:
以下是引用片段:
Please input your words:
a b c d e f
abcdef
总 结
在java.io包中不仅OutputStream用到了Decorator设计模式InputStreamReaderWriter等都用到了此模式而作为个灵活可扩展类库JDK中使用了大量设计模式比如在Swing包中MVC模式RMI中Proxy模式等等对于JDK中模式研究不仅能加深对于模式理解而且还有利于更透彻了解类库结构和组成
0
相关文章读者评论
发表评论 |