装饰模式的体现之一:
BufferedReader 类中readLine()方法
原理:readLine()调用的还是read()方法,在硬盘上一个一个的读取,暂时存储起来,当读取到换行符时就把读取的值返回完成一行数据的读取
模拟BufferedReader类中readLine方法
import java.io.*;
class MyBufferedReader
{
private FileReader r; //私有化成员变量
MyBufferedReader(FileReader r)//将读取流对象传入构造函数
{
this.r=r;
}
public String myReadLine() throws IOException//可以一次读取一行的方法
{//定义临时容器,原BufferReader封装了字符数组
StringBuilder sb = new StringBuilder();//最终数据还是要转成字符串,为了方便,定义StringBuilder容器
int ch = 0;
while ((ch=r.read()) !=-1)
{
if (ch=='\r')//Windows中java换行符是 \r\n
continue;//
if (ch=='\n')
return sb.toString();//当读取到换行时,将缓冲区中字符串返回
else
sb.append((char)ch);//读取不到换行,缓冲区就一直增加,由于ch是read返回的该字符在码表中的int值,所以要强转
}
if(sb.length() !=0) //此判断是为了处理文件末尾没有换行符的情况
return sb.toString();
return null;//方法明确了返回值为String,
}
public void myClose() throws IOException
{
r.close();
}
}
readLine()是read()方法的增强,BufferedReader是FileReader类的增强类,
将被增强类的对象作为参数传入增强类
装饰设计模式
当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,提供加强功能,自定的该类称为装饰类
示例:
class Person{
public void eat(){
System.out.println("吃饭");
}
}
class SuperPerson{//装饰类
private Person p; //将被装饰的类作为成员变量
SuperPerson(Person p){//嵌入到装饰类
this.p = p;
}
public void superEat(){ //装饰类更强大的功能
System.out.println("开胃菜");
p.eat();
System.out.println("饭后甜点");
System.out.println("Smoke~");
}
}
class DecorateDemo{
public static void main(String[] args) {
Person p = new Person();
SuperPerson sp = new SuperPerson(p);
sp.superEat();
}
}
装饰和继承的关系:
通过继承生成子类同样可以达到扩展功能的效果,但是相比之下,装饰模式降低了两个类之间的关联度,具有更高的灵活性和扩展性
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyBufferTextReader
|--MyMediaReader
|--MyBufferMediaReader
|--MyDataReader
|--MyBufferDataReader
class MyBufferReader{
MyBufferReader(MyTextReader text)
{}
MyBufferReader(MyMediaReader media)
{}
}
上面这个类扩展性很差。找到其参数的共同类型。通过多态的形式。可以提高扩展性。
class MyBufferReader extends MyReader{//组合结构
private MyReader r;
MyBufferReader(MyReader r)
{}
}
通过继承将每一个子类都具备缓冲功能。而继承体系比较复杂,并不利于扩展。
现在优化思想。单独描述一下缓冲内容。将需要被缓冲的对象。传递进来。
也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。这样继承体系就变得很简单。优化了体系结构。
优化后的体系:
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferReader//
装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。
装饰模式的体现之二:
BufferedReader的子类LineNumberReader
主要方法:setLineNumber(int x),设置当前行号
和getLineNumber(),获得当前行号
示例:
import java.io.*;
class LineNumberReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("LineNumberReaderDemo.java");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(10);//设置当前行号
while ((line=lnr.readLine()) !=null)
{
System.out.println(lnr.getLineNumber()+" : "+line);
}
lnr.close();
}
}
手动模拟实现一个LineNumberReader类
class MyLineNumberReader extends MyBufferedReader //继承,参考之前的readLine()实现
{
MyLineNumberReader(Reader r){ //继承自父类,省略成员的私有化步奏
super(r);
}
public String myReadLine() throws IOException{
lineNumber++; //相对于父类的readline()仅增加了计数功能
return super.myReadLine();//继承自父类
}
public void setLineNumber(int lineNumber){ //子类特有方法
this.lineNumber = lineNumber;
}
public int getLineNumber(){ //子类特有方法
return lineNumber;
}//关闭流的动作父类中已经实现了,不需要再覆盖,直接调用即可
}