装饰者模式Decorator
实例分析
Decorator装饰或者Wrapper包装这个些词太容易让人想到的是图形用户界面,这些控件方面的应用了。但这仅仅只是一种形象的表达而已,不局限于此。
1 For Example:
Streams是大多数I / O设备的基础抽象结构,它提供了将对象转换成为字节或字符流的操作接口,
使我们可以将一个对象转变成一个文件或内存中的字符串,可以在以后恢复使用。一个简单直接的
方法是定义一个抽象的Stream类,它有两个子类MemoryStream与FileStream。但假定我们还希望能够做下面一些事情:
• 用不同的压缩算法(行程编码, Lempel-Ziv等)对数据流进行压缩。
• 将流数据简化为7位A S C I I码字符,这样它就可以在A S C I I信道上传输。
Decorator模式提供的将这些功能添加到Stream中方法很巧妙。下面的类图给出了一个解决问题的方法。
Stream抽象类维持了一个内部缓冲区并提供一些操作( PutInt, PutString)用于将数据存入流中。
一旦这个缓冲区满了,Stream就会调用抽象操作HandleBufferFull进行实际数据传输。
在FileStream中重定义了这个操作,将缓冲区中的数据传输到文件中去。
这里的关键类是StreamDecorator,它维持了一个指向组件流的指针并将请求转发给它,
StreamDecorator子类重定义HandleBufferFull 操作并且在调用StreamDecorator的HandleBufferFull操作之前执行一些额外的动作。
例如,CompressingStream子类用于压缩数据,而ASCII7Stream将数据转换成7位ASCII码。
现在我们创建FileStream类,它首先将数据压缩,然后将压缩了的二进制数据转换成为7位ASCII码,
我们用CompressingStream和ASCII7Stream装饰FileStream:
Stream* aStream = new ASCII7Stream (
new CompressingStream (
new FileStream("aFileStream")
)
);
aStream->PutInt(12);
aStream->PutString("aString");
2 相关模式:
- Adapter模式:Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
- Composite模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责—它的目的不在于对象聚集。
- Strategy模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变对象的内核。这是改变对象的两种途径。
private
static
void
testBufferedOutputStream() {
// 创建“文件输出流”对应的BufferedOutputStream
// 它对应缓冲区的大小是16,即缓冲区的数据>=16时,会自动将缓冲区的内容写入到输出流。
try
{
File file =
new
File(
"out.txt"
);
OutputStream out =
new
BufferedOutputStream(
new
FileOutputStream(file),
16
);
// 将ArrayLetters数组的前10个字节写入到输出流中
out.write(ArrayLetters,
0
,
10
);
// 将“换行符\n”写入到输出流中
out.write(
'\n'
);
// TODO!
//out.flush();
readUserInput() ;
out.close();
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch
(SecurityException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
}
这里的可以让写入功能自动缓存到buffer中,设置合适的大小,可以达到减少磁盘交互。加快写入速度。不用手动实现写入文件的代码了。
public void copyFile(String oldPath, String newPath) { try { int bytesum = 0; int byteread = 0; File oldfile = new File(oldPath); if (oldfile.exists()) { //文件存在时 InputStream inStream = new FileInputStream(oldPath); //读入原文件 FileOutputStream fs = new FileOutputStream(newPath); byte[] buffer = new byte[1444]; int length; while ( (byteread = inStream.read(buffer)) != -1) { bytesum += byteread; //字节数 文件大小 System.out.println(bytesum); fs.write(buffer, 0, byteread); } inStream.close(); } } catch (Exception e) { System.out.println("复制单个文件操作出错"); e.printStackTrace(); } }
同样 还有input也是类似的模式