您的位置:首页 > 其它

装饰器模式

2015-09-23 16:09 239 查看
装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。



 在装饰模式中的角色有:

  ●  抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

  ●  具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。

  ●  装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

  ●  具体装饰([b]ConcreteDecorator)角色:[/b]负责给构件对象“贴上”附加的责任。

InputStream类型中的装饰模式

  InputStream类型中的装饰模式是半透明的。为了说明这一点,不妨看一看作装饰模式的抽象构件角色的InputStream的源代码。这个抽象类声明了九个方法,并给出了其中八个的实现,另外一个是抽象方法,需要由子类实现。

public abstract class InputStream implements Closeable {

public abstract int read() throws IOException;

public int read(byte b[]) throws IOException {}

public int read(byte b[], int off, int len) throws IOException {}

public long skip(long n) throws IOException {}

public int available() throws IOException {}

public void close() throws IOException {}

public synchronized void mark(int readlimit) {}

public synchronized void reset() throws IOException {}

public boolean markSupported() {}

}


  

  下面是作为装饰模式的抽象装饰角色FilterInputStream类的源代码。可以看出,FilterInputStream的接口与InputStream的接口是完全一致的。也就是说,直到这一步,还是与装饰模式相符合的。

public class FilterInputStream extends InputStream {
protected FilterInputStream(InputStream in) {}

public int read() throws IOException {}

public int read(byte b[]) throws IOException {}

public int read(byte b[], int off, int len) throws IOException {}

public long skip(long n) throws IOException {}

public int available() throws IOException {}

public void close() throws IOException {}

public synchronized void mark(int readlimit) {}

public synchronized void reset() throws IOException {}

public boolean markSupported() {}
}


  

  下面是具体装饰角色PushbackInputStream的源代码。

public class PushbackInputStream extends FilterInputStream {
private void ensureOpen() throws IOException {}

public PushbackInputStream(InputStream in, int size) {}

public PushbackInputStream(InputStream in) {}

public int read() throws IOException {}

public int read(byte[] b, int off, int len) throws IOException {}

public void unread(int b) throws IOException {}

public void unread(byte[] b, int off, int len) throws IOException {}

public void unread(byte[] b) throws IOException {}

public int available() throws IOException {}

public long skip(long n) throws IOException {}

public boolean markSupported() {}

public synchronized void mark(int readlimit) {}

public synchronized void reset() throws IOException {}

public synchronized void close() throws IOException {}
}


  查看源码,你会发现,这个装饰类提供了额外的方法unread(),这就意味着PushbackInputStream是一个半透明的装饰类。换言 之,它破坏了理想的装饰模式的要求。如果客户端持有一个类型为InputStream对象的引用in的话,那么如果in的真实类型是 PushbackInputStream的话,只要客户端不需要使用unread()方法,那么客户端一般没有问题。但是如果客户端必须使用这个方法,就 必须进行向下类型转换。将in的类型转换成为PushbackInputStream之后才可能调用这个方法。但是,这个类型转换意味着客户端必须知道它 拿到的引用是指向一个类型为PushbackInputStream的对象。这就破坏了使用装饰模式的原始用意。

  现实世界与理论总归是有一段差距的。纯粹的装饰模式在真实的系统中很难找到。一般所遇到的,都是这种半透明的装饰模式。

  下面是使用I/O流读取文件内容的简单操作示例。

public class IOTest {

public static void main(String[] args) throws IOException {
// 流式读取文件
DataInputStream dis = null;
try{
dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream("test.txt")
)
);
//读取文件内容
byte[] bs = new byte[dis.available()];
dis.read(bs);
String content = new String(bs);
System.out.println(content);
}finally{
dis.close();
}
}

}


  观察上面的代码,会发现最里层是一个FileInputStream对象,然后把它传递给一个BufferedInputStream对象,经过BufferedInputStream处理,再把处理后的对象传递给了DataInputStream对象进行处理,这个过程其实就是装饰器的组装过程,FileInputStream对象相当于原始的被装饰的对象,而BufferedInputStream对象和DataInputStream对象则相当于装饰器。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: