您的位置:首页 > 其它

装饰者设计模式

2009-02-21 17:39 423 查看
定义:动态将扩展功能附加到对象上,替代继承的另一种选择。类图如下:

(图片引自http://www.cnblogs.com/NeeoMeng/articles/1127974.html


定义看起来不是很好理解,其实只要用过Java IO,我们已经在用装饰者这种设计模式了 -, -

先看看java io package里对于有关InputStream类的分布情况



上图中,FilterInputStream即可被看作Decorator Class。

照猫画虎,我们也可以编写自己的Java I/O装饰着对象了。

如实现将输入流内所有字符变为大写或者小写。我们需要做的仅仅是继承FilterInput类,覆写两个方法即可。

问题来了,为什么不直接同StreamBufferInputStream类一样继承InputStream实现转换大小写的功能呢?

其实,如果只是单纯的继承关系,那么我们想实现既用Buffer,又要让它大小写转换将怎么办呢~建个UpperCaseStringBufferInputStream同样继承InputStream? 此方法肯定不是王道,逐渐的,类会多的让人想死,Java的设计者自然也想到了这样的问题。

用装饰者模式可以轻松解决爆炸式类继承的问题,如果还有点晕,看了下面代码估计就懂了。

UpperCaseInputStream类,继承FilterInputStream

覆写InputStream里的两个主要read()方法

import java.io.*;

public class UpperCaseInputStream extends FilterInputStream{
public UpperCaseInputStream(InputStream in) {
super(in);
}

public int read() throws IOException{
int c = super.read();
return c == -1 ? c : Character.toUpperCase(c);
}

public int read(byte[] b, int offset, int length) throws IOException {
int c = super.read(b, offset, length);
for(int i = offset; i < offset+length; i++){
b[i] = (byte)Character.toUpperCase((char)b[i]);
}
return c;
}
}


同理,Java I/O中的Reader类也是采用了装饰者的设计模式

Reader比InputStream相对复杂点,如果某些方法或者构造函数不知如何覆写,可参照JDK源码中同样继承Reader的相关类,如BufferedReader.

两个重要的方法,依旧是read()

LowerCaseReader类继承自FilterReader

public class LowerCaseReader extends FilterReader{
private Reader r;

public LowerCaseReader(Reader r){
super(r);
this.r = r;
}

public void close() throws IOException {
// TODO Auto-generated method stub
synchronized (lock) {
if (r == null)
return;
r.close();
r = null;
}
if (r == null)
return;
else
r.close();
}

public int read() throws IOException{
int c = super.read();
return c == -1 ? c : Character.toLowerCase((char)c);
}

public int read(char[] ch, int offset, int length) throws IOException {
int c = super.read(ch, offset, length);
for(int i = offset; i < offset+length; i++){
ch[i] = (char)Character.toLowerCase((char)ch[i]);
}
return c;
}
}


编写个简单的测试类:

ReaderTest

public class ReaderTest {

/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
int c;
String line = null;

// UpperCaseInputStream
// 装饰类如何用
InputStream in = new UpperCaseInputStream(new FileInputStream("test.txt"));
while((c = in.read()) > 0){
System.out.print((char)c);
}

in.close();
in = null;

// LowerCaseReader
// 喜欢ReadLine的朋友可以做Reader的装饰类
// BufferedReader被LowerCaseReader所修饰
// 多写几个修饰类,由于构造函数接的都是Reader,当然可以叠加
// Java的向下转型在修饰者的应用中起了相当关键的作用
BufferedReader br = new BufferedReader(new LowerCaseReader(new FileReader("test2.txt")));
// BufferedReader的readLine方法调用fill调用Reader的read方法
// 由于构造时是以LowerCaseReader构造,所以实际上调用了其read方法,讲小写显示
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
br = null;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: