java 装饰模式 stream_从java的InputStream类认识装饰者模式

IO操作是程序中经常遇到的,那java中提供的IO操作有哪些呢?

java中先分成两大类:字节流读写操作(input stream/output stream)和字符流读写操作(reader/writer),流即是对数据输入/输出设备的抽象。

上面提到的四个类是java IO操作的基类,其对应衍生了很多子类,下面基于input stream来说明装饰者模式。

什么是装饰者模式?

俄罗斯套娃大家都非常熟悉,装饰者模式跟俄罗斯套娃就有点像,你想要什么样的娃娃,就可以在原有的基础上套上你要的娃娃的模样,这样你在不改变原来的娃娃的基础上,在外边套上什么娃娃,就变成了什么娃娃。

下面看看IO家族是怎么使用装饰者模式的?

先看看input stream的家族成员

40328839b4055476eec2c9a6a2dd679d.png

咋一看成员还真多,子孙后代满堂啊,这怎么记得住!诶,这里面可是有名堂的。

先看子代,子代是怎么来的呢?那是很久之前的事了,据说java刚刚被创建的时候就有Input Stream了,作为负责读取数据的始祖,那不同的后代就负责处理来源不同的数据吧:

ByteArrayInputStream负责处理字节数组

FileInputStream负责处理文件

ObjectInputStream负责处理被序列化的对象

PipedInputStream负责处理其他线程的输入流

SequenceInputStream负责处理多个输入流合并成一个流,比如含有流的集合

StringBufferInputStream负责读取StringBuffer中的数据

AudioInputStream负责处理音频流

可是,后来发现从硬盘中读取数据太慢了呀,怎么办?

要不弄个buffer,读取数据时先从buffer中读取,找不到再去硬盘里读,不就快多了吗。可是我每个子类都要拥有这个功能怎么办?在父类中统一实现,不好,如果我在使用buffer时想要跳过几个字节那不是父类又得增加一个方法,我想增加其他功能时,不是父类又要被修改,这样就违反了开闭原则,扩展性实在是太差啦!那怎么办?这就说到装饰着模式了。

就像上面提到的俄罗斯套娃模式,把现有的子类作为实心娃娃,外面套一个BufferInputStream,就拥有了缓冲的功能,套一个DataInputStream,就拥有了从底层输入流读取原始Java数据类型的功能。并且还可以层层嵌套,这样就拥有了各种需要的功能。并且每个子类都能获得全功能还不用每个子类单独去实现,是不是很爽。通过上面的分析,我们可以得出以下结论:

实心娃娃:InputStream子类(除了FilterInputStream)

套娃壳模板:FilterInputStream

套娃壳:FilterInputStream子类

那是如何实现这个模式的呢?

首先,通过套娃壳的构造函数将实心娃娃放进去;

再者,套娃壳+实心娃娃能作为其他壳的实心娃娃;

所以可以看到,套娃壳都继承了InputStream,并且通过构造函数传进去。

那为什么还要FilterInputStream呢,不是让套娃壳直接继承InputStream?

我想大概是InputStream儿子已经很多了,在加那么多壳儿子不合适,而且壳是用来修饰他的儿子的,不是真的他儿子,需要与他的真儿子区分开,于是就有了一个模板儿子,而壳则由模板儿子去生成。

现在看到下面这个例子就很好理解了吧:先读取文件流,然后套上缓冲功能,最后直接将流进行GZIP解压缩,一气呵成

InputStream inputStream = new GZIPInputStream(new BufferedInputStream(new FileInputStream("D:\\temp\\test.txt")));

如有理解错误,请多多指教,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值