为什么 Java IO 体系中的装饰者模式中,一定用弄个 FilterInputStream 作为 DataInputStream, BufferedInputStream 的父类?

2020-01-18 12:47:15 +08:00
 amiwrong123

直接让 BufferedInputStream 继承抽象类 InputStream,再令其构造器的实现为类似:

class BufferedInputStream extends InputStream{
    protected volatile InputStream in;
    protected BufferedInputStream(InputStream in) {
    this.in = in;
    }

这样不行吗

或者说只是为了抽取处子类的公共部分吗

4015 次点击
所在节点    Java
8 条回复
guyeu
2020-01-18 14:23:07 +08:00
FilterInputStream 是代理模式,DataInputStream 和 BufferedInputStream 都使用了代理这个特性。
bagel
2020-01-18 14:44:31 +08:00
这是 x 模式,那是 y 模式,中间还用到了 z 模式……这让我想起项飙吐槽西方人类学:一些人类学家说一些话,以便让别的人类学家有话可说。
KunMinX
2020-01-18 15:26:24 +08:00
okio 解君愁
LowBCoder
2020-01-18 16:48:34 +08:00
@guyeu FilterInputStream 是装饰器模式。。。
我个人的理解(有不对的地方请指出哈)是 FilterInputStream 这个的子类,是流读取的方法的抽象( Data 读取、缓存读取),InputStream 的子类是流类型的抽象(比如文件读取、字节读取),了解下装饰器模式你就会发现,装饰器模式的好处是在运行时扩充功能,所以 IO 用继承去处理流类型的抽象,然后用装饰器模式去处理流读取方法的抽象,如果全部用继承的话,流读取方法的抽象和流类型的抽象的组合就需要多一层继承关系去处理,会增加很多代码量,也不好拓展。
guyeu
2020-01-18 19:01:43 +08:00
@LowBCoder #4 说 FilterInputStream 是 InputStream 的代理而不是装饰器的原因如下:
1. FilterInputStream 并没有给 InputStream 扩展任何功能,只是持有了一个 InputStream 的实例,所有的操作都转交给持有的这个 InputStream 的实例去做;
2. BufferedInputStream 和 BufferedInputStream 可以说是装饰器模式,都为 InputStream 增加了不属于它的特性;

抽象出一个用于代理的实现类而不是把同样的方法按照挨个在 BufferedInputStream 和 BufferedInputStream 里实现一遍,最显而易见的原因就是为了使代码简介,使用到了代理这个特性,所以抽象出一个代理者。
D3EP
2020-01-19 14:30:02 +08:00
FilterInputStream 类似于 Guava 中的 ForwardingXXX 类,比如 ForwardingQueue。
主要是为了在添加新功能时,避免重写其它方法。
代理模式和装饰器模式区分没那么严格,都是持有一个对象,然后添加一些功能。
LowBCoder
2020-01-20 10:47:21 +08:00
@guyeu 受教了,感谢回复
LowBCoder
2020-01-20 10:49:32 +08:00
@guyeu FilterInputStream 确实只是持有一个 InputStream 实例,这一块代码我刚才又去看了下,之前确实是自己没有结合代码理解透彻

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/638937

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX