看字面意思,装饰者就是把一个对象装饰一下,那么必要要有一个装饰着和被装饰着,被装饰者是比较原始的东西,比如一个原始的木门,大家都涂成各种颜色什么的,这里木门就是个被装饰者,各种颜料就是装饰着.装饰者要装饰被装饰者,必然要拥有一个被装饰着的对象,现在来看java I/O,I/O的本质是从文件,网络等地方读取字节流,FileInputStream是从文件中读取字节流,很原始了,它就是一个被装饰者,其他还有StringBufferInputStream,ByteArrayInputStream等,装饰着就是BufferdInputStream,猜测BufferdInputStream必然会有一个被装饰着的对象,它提供的功能是缓冲区,它可以给前面所有的被装饰者提供缓冲功能。先看headFirst设计模式一书给出的例子,比较好懂,现在假设FileInputStream已经读出字节了,要把读出来的字节中小写字母全部转化为大写字母,就是把FileInputStream装饰一下,设计一个这样的类:
public class LowerCaseInputStream extends FilterInputStream {
protected LowerCaseInputStream(InputStream in) {
super(in);//调用父类FilterInputStream,父类中持有一个被装饰者InputStream的对象
}
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1)?c:Character.toLowerCase((char)c);
}
}
看LowerCaseInputStream,read方法相当于真正的装饰方法,要实现小写转大写的,如果传入一个FileInputStream,就持有了被装饰者对象,可以肆意的装饰它了,看怎么使用的:
String path = new String(System.getProperty("user.dir")+File.separator+"file/test.txt");
try {
InputStream is = new FileInputStream(path);//没有使用装饰者的时候
int c;
while((c=is.read())>0){
System.out.print((char)c);
}
System.out.println();
System.out.println("使用装饰者模式输出:");
InputStream myis = new LowerCaseInputStream(new FileInputStream(path));
while((c=myis.read())>0){
System.out.print((char)c);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
输出:
bCd
使用装饰者模式:
bcd
很简单,一个自己的装饰者就做好了,当然你还可以有其他装饰着,如BufferdInputStream等,像下面使用:
InputStream myis = new BufferedInputStream(new LowerCaseInputStream(new FileInputStream(path)));
这样就有两个装饰着同时修饰FileInputStream了。很难理解为什么要这么用,直接用FileInputStream读出来然后再转大小写不行吗?可以这样来理解,木门为什么不直接在生产的时候就加个搞的比较好看呢?,因为木门需求还没有完全确定,每个用户需要的颜色都不一样,也就是说木门只提供最基本的功能,看FileInputStream类,它也只提供最基本的功能,如读写字节什么的,但是至于什么缓冲功能,大小写转换就需要等程序员想用的时候自己来选择,在java I/O中,FileInputStream和BufferedInputStream都继承InputStream,我的理解是:会有很多装饰者和很多被装饰者,但是装饰者要持有被装饰者的对象,假设FileInputStream等被装饰者都继承了InputStream了,这样只要传入一个InputStream进去装饰着BufferedInputStream,它就能持有所有被装饰的对象了,那么BufferedInputStream为什么还有继承InputStream呢?因为像这样的代码:
new LowerCaseInputStream(new FileInputStream(path),把被装饰者装饰了之后返回的对象是什么呢?必要还要返回被装饰者的对象,你不能把门涂层颜色就不是门了吧?所以装饰着也继承于InputStream,但是它不是直接继承InputStream,而是继承FilterInputStream,但是FilterInputStream继承InputStream,有一层FilterInputStream间接来继承InputStream,而继承与FilterInputStream的所有子类都是装饰者类,在FilterInputStream中持有一个被装饰者类的对象,这样子类就不用持有了被装饰者对象了,都从父类FilterInputStream继承过来了。最后看一下java I/O的BufferedInputStream源代码:
public BufferedInputStream(InputStream in) {
this(in, defaultBufferSize);
}
public synchronized int read() throws IOException {
if (pos >= count) {
fill();//这里面会调用被装饰者的read方法
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
其实它跟LowerCaseInputStream是一样的,构造函数接受一个InputStream的被装饰者,read函数是具体的装饰功能。最后上个java I/O的包图结构
java.io.InputStream (implements java.io.Closeable)
从中可以看出FilterInputStream是跟其他的FileInputStream等平行的,都是继承InputStream,FilterInputStream的子类都是装饰者类。
分享到:
相关推荐
【Java面试题】谈谈对Java多态的理解
在eclipse中运行如下代码,很多小伙伴在纠结到底应该是多少,其实正确结果应该是0!!! int i = 0; i = i++; System.out.println("i的值是 : " + i); 这是和JVM的内存分配有关,JVM在处理这段带代码时,会先把i++的...
代码演示对java中多态的理解 从代码演示中更好的理解多态的作用
1谈谈对java平台的理解1
第1讲 谈谈你对Java平台的理解1
谈谈对Java的认识.pdf
java的面向对象的理解,java概述,基本的java思想
第01讲丨谈谈你对Java平台的理解?.html
先谈谈我对java的一些认识。我选择java,是因为他语法简单,功能强大,从web,到桌面,到嵌入式,无所不能。但当我进一步了解了java后,感叹,java原来也有许多缺点。下面我就列举一下我认为的java的优缺点。
谈谈NIO的理解Java系列2021.pdf
NULL 博文链接:https://deony2jacob1314.iteye.com/blog/1845769
很多人都不明白其原理,下面我来谈谈我的理解: 1. node的优点:I/O密集型处理是node的强项,因为node的I/O请求都是异步的(如:sql查询请求、文件流操作操作请求、http请求…) a. 什么是异步? 异步:发出操作指令...
自然辨证法考试习题、原题,仅供参考
谈谈Java中的布局管理器.pdf
谈谈java 反射机制
通过实例程序验证与优化谈谈网上很多对于Java DCL的一些误解以及为何要理解Java内存模型.doc
类图用于描述系统中所包含的类以及它们之间的相互关系,帮助人们简化对系统的理解,它是系统分析和设计阶段的重要产物,也是系统编码和测试的重要模型依据。接下来我们就来谈谈类图的组成,在下一篇中我们将讨论一下...
谈谈你对JVM的理解?
谈谈你对否定之否定之规律的理解及其方法论意义.pdf
另外,我们在eclipse或者IDEA中编辑Java代码时,它们是怎么知道我们的对象有哪些方法,输入一个点就能给提示呢? 带着问题我们来谈谈反射。 概念 反射:是将一个类的各个部分封装为其他对象,这就是反射机制。 看着...