前面提到的那些类都只是对字节数组,或者字符数组这类数据的操作,
如果我们想要想在流中输入或输出的是Long,Int,Double,这样的基本类型呢?
其实这样的类 java io代码中已经有了,即为DataInputStream,和DataOutputStream
并且使用了一个设计模式——装饰模式。
一,装饰模式简介
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
来看以下的例子:
public class DataOutputStreamExample {
public static void main(String[] args) throws Exception {
long a=12131414;
//创建一个字节数组输出流
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
//放入dataoutputStraam进行装饰
DataOutputStream dataOutputStream=new DataOutputStream(outputStream);
//写入long
dataOutputStream.writeLong(a);
//将流中的内容输出到byte[]中
byte[] bytes= outputStream.toByteArray();
//再创建byte的输入流,bytes作为数据源
ByteArrayInputStream inputStream=new ByteArrayInputStream(bytes);
//装饰
DataInputStream dataInputStream=new DataInputStream(inputStream);
//输出
System.out.println(dataInputStream.readLong());
}
}
以上的代码中 ByteArrayOutputStream 继承了OutputStream,
后面又将OutPutStream作为构造参数传给了DataOutputStream,
这样,那个简单的输出流,就可以写入Long型了。
new DataOutputStream(outputStream)
这是如何实现的呢?,简单的包装就扩展了原本的类的功能
实际的原因很简单,就是在这个DataOutputStream中有一个成员变量即是OutputSteam 。任何继承了OutputSteam这个类的子类都可以作为构造参数传入,实现功能的扩展。
以下为FilterOutSteam的源码:
protected OutputStream out;
public FilterOutputStream(OutputStream out) {
this.out = out;
}
二,各个类在装饰模式中扮演的角色
1.抽象构件(Component)角色:由InputStream,和 OutputSteam扮演。这是一个抽象类,为各种子类型处理器提供统一的接口。
(也就是说,只要一个类继承了这个抽象构建,就能使用装饰角色进行装饰)
2.具体构建(Concrete Component)角色:由ByteArrayInputStream、FileInputStream以及StringBufferInputStream等原始流处理器扮演。它们实现了抽象构建角色所规定的接口,可以被链接流处理器所装饰。
(一个符合抽象构件规范的具体构件)
-
抽象装饰(Decorator)角色:由FilterInputStream扮演。它实现了InputStream所规定的接口。
(可以理解为对所有装饰角色的一个规范,任何继承了这个类的具体装饰角色,可以装饰继承了抽象构件角色的类) -
具体装饰(Concrete Decorator)角色:由几个类扮演,分别是DateInputStream、BufferedInputStream 以及两个不常用到的类LineNumberInputStream和PushbackInputStream。
三,个人理解及总结
抽象构件(Component)角色 和 抽象装饰(Decorator)角色,
是对被装饰角色 和 装饰角色的一个规范。
就像是两个可以组合的零件,只要符合规范,任意一个都可以被随意替换,这便是装饰模式的好处吧。
网友评论