装饰模式的体现之一:
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==' ')//Windows中java换行符是 continue;// if (ch==' ') 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; }//关闭流的动作父类中已经实现了,不需要再覆盖,直接调用即可 }