Java IO流以及装饰器模式在其上的运用
流概述
Java中,流是一种有序的字节序列,可以有任意的长度。从应用流向目的地称为输出流,从目的地流向应用称为输入流。
Java的流族谱
Java的 java.io 包中囊括了整个流的家族,输出流和输入流的谱系如下所示:

InputStream和OutputStream
InputStream和OutputStream分别是输入输出流的顶级抽象父类,只定义了一些抽象方法供子类实现。
在输出流OutputStream中,如果你需要向一个输出流写入数据,可以调用 void write(int b) 方法,这个方法会将b的低八位写入流中,高24位将会被自动忽略。如果想要批量写入数据呢,那么可以调用 void write(byte[] b) 方法将一个字节数组的内容全部写入流中,同时还有 void write(byte[] b, int off, int len) 可以让你指定从哪里写入多少数据。
如果你希望你向流中写入的数据能够尽快地输送到目的地,比如说文件,那么可以在写入数据后,调用 flush() 方法将当前输出流刷到操作系统层面的缓冲区中。不过需要注意的是,此方法并不保证数据立马就能刷到实际的物理目的地(比如说存储)。
使用完流后应该调用其 close() 方法将流关闭,流关闭时,将会先flush,后关闭。
在输入流InputStream中,可以通过 int read() 方法来从流中读取一个字节,批量读取字节可以通过 int read(byte[] b) 或者 int read(byte[] b, int off, int len) 来实现,这两个方法的返回值为实际读取到的字节数。如果需要重复读取流中某段数据,可以在读取之前先使用 void mark(int readlimit) 方法在当前位置做一个记号,之后通过 void reset() 方法返回到之前做标记的位置,不过在做这些标记操作之前,需要先通过 boolean markSupported() 方法来确定该流是否支持标记。如果对某些可预知的数据不感兴趣,可以使用 long skip(long n) 来调过一些流中的一些数据。
使用完流,无论是输入还是输出流,都要调用其 close() 方法对其进行关闭。
装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种设计模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
以InputStream为例,它是一个抽象类:
public abstract class InputStream implements Closeable {
...
...
}
并定义有抽象方法
public abstract int read() throws IOException;
该抽象方法由具体的子类去实现,通过InputStream的族谱图可以看到,直接继承了InputStream,并且提供某一特定功能的子类有:
- ByteArrayInputStream
- FileInputStream
- ObjectInputStream
- PipedInputStream
- SequenceInputStream
- StringBufferInputStream
这些子类都具有特定的功能,比如说,FileInputStream代表一个文件输入流并提供读取文件内容的功能,ObjectInputStream提供了对象反序列化的功能。
InputStream这个抽象类有一个子类与上述其它子类非常不同,这个子类就是 FilterInputStream ,可参见上图中的InputStream族谱图。
翻开FilterInputStream的代码,我们可以看到,它内部又维护了一个InputStream的成员对象,并且它的所有方法,都是调用这个成员对象的同名方法。换句话说,FilterInputStream它什么事都不做。就是把调用委托给内部的InputStream成员对象。如下所示:
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
FilterInputStream的又有其子类,分别是:
- BufferedInputStream
- DataInputStream
- LineNumberInputStream
- PushbackInputStream
虽然从上面代码看FilterInputStream并没有做什么有卵用的事,但是它的子类可不同了,以BufferedInputStream为例,这个类提供了提前读取数据的功能,也就是缓冲的功能。可以看看它的read方法:
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
可以看到,当pos>=count时,意即需要提前缓冲一些数据的时候到了,那么就会调用fill()将缓冲区加满,以便后续读取。 由于本文只讨论io流的装饰器模式,所以关于具体实现细节将不会展开讨论,比如本文不会讨论fill()方法是如何实现的,在这里可以先将它当做一个黑盒子。
从这里可以开始感受到,BufferedInputStream就是一个装饰者,它能为一个原本没有缓冲功能的InputStream添加上缓冲的功能。
比如我们常用的FileInputStream,它并没有缓冲功能,我们每次调用read,都会向操作系统发起调用索要数据。假如我们通过BufferedInputStream来 装饰 它,那么每次调用read,会预先向操作系统多拿一些数据,这样就不知不觉中提高了程序的性能。如以下代码所示:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("/home/user/abc.txt")));
同理,对于其它的FilterInputStream的子类,其作用也是一样的,那就是装饰一个InputStream,为它添加它原本不具有的功能。OutputStream以及家属对于装饰器模式的体现,也以此类推。
JDK中的io流的设计是设计模式中装饰器模式的一个经典示范,如果细心发现,JDK中还有许多其它设计模式的体现,比如说监听者模式等等。
Java IO流以及装饰器模式在其上的运用的更多相关文章
- java进阶系列之装饰器模式
1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- IO流与装饰者模式
java使用IO流来处理不同设备之间数据的交互;所有的IO操作实际上都是对 Stream 的操作 从功能上划分: 输入流: 当数据从源进入的编写的程序时,称它为输入流; 输出流: 从程序输出回另一个源 ...
- Java设计模式之装饰器模式
1.装饰器模式的定义(保持接口,扩展功能) Decorate装饰器,顾名思义,就是动态的给一个对象添加一些额外的职责,就好比对房子进行装修一样. 2.装饰器模式的特征 具有一个装饰对象. 必须拥有与被 ...
- Java设计模式系列-装饰器模式
原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...
- java IO流详解
流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- Java IO流学习总结
Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- Java IO流详尽解析
流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
随机推荐
- 【转】 CoreGraphics QuartzCore CGContextTranslateCTM 用法
原文:http://blog.csdn.net/sqc3375177/article/details/25708447 CoreGraphics.h 一些常用旋转常量 #define M_E 2.71 ...
- App上线基本流程
还可参考的:http://www.cocoachina.com/bbs/read.php?tid=330302 iOS项目上传前期准备材料: 1.已有开发者账号 2.已有发布证书 3.一张1024*1 ...
- iOS单例的两种实现
单例模式算是开发中比较常见的一种模式了.在iOS中,单例有两种实现方式(至少我目前只发现两种).根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_o ...
- jq 图片裁剪
1.html <div class="jcropbox" style="display: none"> <img src="&quo ...
- HDOJ 2037简单的贪心算法
代码: #include<iostream> using namespace std; int main() { int n,s,t1[100],t2[100],i,t,j; while( ...
- 平衡搜索树(一) AVL树
AVL树 AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的.它能保持二叉树的高度 平衡,尽量降低二叉树的高度,减 ...
- 【BZOJ2038】【莫队】小z的袜子
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜 ...
- access_token的获取2
概述 access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存. access_token的存储至少要保留512个字符空间.acces ...
- YII 小部件 解决多选按钮和单选按钮不在同一水平上 'separator'=>' '
主要是添加separator属性(这里)$hoddy,$sex在控制器里面定义的数组,然后render传过来的 <td> <?php echo $form-> ...
- Start Your Django Project in Nginx with uWsgi
Step 0:Install A,B,C,blabla needed This can be seen in my another article in the blog.click here(una ...