——- android培训、java培训、期待与您交流! ———-
装饰设计模式
概述及分析
装饰设计模式就是对原有的类进行功能的加强,修饰.
示例:
class Person{
void chifan(){
System.out.println( "吃饭");
}
}
//采用装饰的方式增强Person类
//这个类的出现是为了增强Person而出现的
class NewPerson{
private Person p;
NewPerson(Person p){
this.p = p;
}
public void chifan(){
System.out.println( "开胃酒");
p.chifan();
System.out.println( "甜点");
}
}
//采用继承的方式增强Person类
class NewPerson2 extends Person{
public void chifan(){
System.out.println( "开胃酒");
super.chifan();
System.out.println( "甜点");
}
}
public class PersonDemo{
public static void main(String[] args){
Person p = new Person();
NewPerson np1 = new NewPerson(p);
np1.chifan();
System.out.println( "---------------");
NewPerson2 np2 = new NewPerson2();
np2.chifan();
}
}
运行结果如下:
装饰和继承都能实现一样的特点:进行功能的扩展增强。有什么区别呢?
首先有一个继承体系:
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作为结束标记。
代码:
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
class MyBufferedReader{
private Reader r;
//定义一个数组作为缓冲区
private char[] buf = new char[1024];
//定义一个指针用于操作这个数组中的元素,当操作到最后一个元素后,指针应该归零
private int pos = 0;
//定义一个计数器用于记录缓冲区中的数据个数,当该数据减到0,就从源中继续获取数据到缓冲区中
private int count = 0;
MyBufferedReader(Reader r){
this .r = r;
}
//该方法从缓冲区中一次取一个字符
public int myRead() throws IOException {
//从源中获取一批数据到缓冲区中,需要先做判断,只有计数器为0时,才需要从源中获取数据
if (count == 0){
count = r.read(buf);
//每次获取数据到缓冲区后,角标归零
pos = 0;
}
if (count < 0)
return -1;
char ch = buf[pos];
pos++;
count--;
return ch;
}
public String myReadLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch = 0;
while ((ch = myRead()) != -1){
if (ch == '\r' )
continue ;
if (ch == '\n' )
return sb.toString();
//将从缓冲区读到的字符,存储到缓存行数据的缓冲区中
sb.append(( char )ch);
}
if (sb.length() != 0){
return sb.toString();
}
return null ;
}
public void myClose() throws IOException {
r.close();
}
}
public class MyBufferedReaderDemo{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt" );
MyBufferedReader bufr = new MyBufferedReader(fr);
String line = null ;
while ((line = bufr.myReadLine()) != null){
System.out.println(line);
}
bufr.myClose();
}
}
运行结果: