装饰和继承都能实现一样的特点:进行功能的扩展增强。有什么区别呢?
首先有一个继承体系:
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
如果想要对操作的动作进行效率的提高,按照面向对象,可以通过继承的方式对具体的对象进行功能的扩展,那么就需要加入缓冲技术。
Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本的对象
|--MediaWriter:用于操作媒体
|--BufferMediaWriter:加入了缓冲技术的操作媒体的对象
以上方式并不理想,如果这个体系需要再进行功能扩展,又多了更多流对象。
这样就会发现只为提高功能,导致继承体系越来越臃肿,不够灵活。
重新思考问题:
既然加入的都是同一种技术--缓冲。
前一种是让缓冲和自己的流对象相结合。
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。
- class Buffer {
- Buffer(TextWriter w){}
- Buffer(MediaWriter w){}
- }
复制代码 简化为:
- class BufferedWriter extends Writer{
- BufferedWriter(Writer w){}
- }
复制代码
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
|--BufferedWriter:用于提高效率
可见:装饰比继承灵活。
特点:装饰类和被装饰类都必须所属同一个接口或者父类。
练习:
自定义一个读取缓冲区类,模拟一个BufferedReader。
分析:
缓冲区中无非就是封装了一个数组,并对外提供了更多的方法对数组进行访问,其实这些方法最终操作的都是数组的角标。
缓冲的原理:
其实就是从源中获取一批数据到缓冲区中,再从缓冲区中不断地取出一个一个数据。
在此次取完后,再从源中继续取一批数据进缓冲区,当源中的数据取完时,用-1作为结束标记。
代码: