提出问题
今天在coding的时候发现了个问题,使用流的时候,处理流会包装一个节点流,但是在流关闭的时候,我们只需要关闭处理流,被包装的节点流都不关闭,这是怎么回事呢,我们以FileReader 和BufferedReader为例子
package src.main.java.com.Io; import java.io.BufferedReader; import java.io.FileReader; /** * 字符方式 * BufferedReader 带有缓冲区的 字符输入流 * BufferedWriter 带有缓冲区的 字符输出流 * * @author liuhuxiang * @version $Id: BufferedReaderTest01.java, v 0.1 2018年06月01日 15:03 liuhuxiang Exp $ * 关闭最外层的包装即可(装饰者模式) * readLine() 方法,一读读一行 * 这里为了简单些,异常直接抛出,没有处理 */ public class BufferedReaderTest01 { public static void main(String[] args) throws Exception { String path = "D:\\work\\BufferedReaderTest01.java"; BufferedReader bufferedReader = new BufferedReader(new FileReader(path)); //根据流出现的位置 节点流/处理流 //FileReader 节点流,就是一个节点,被别人包装的 //BufferedReader 处理流/节点流 String temp=null; while((temp=bufferedReader.readLine())!=null){ System.out.println(temp); } // 这里注意,要关闭,只要关闭最外层的包装流即可,这里涉及一个装饰者模式 bufferedReader.close(); } }
上面代码我们发现,只关闭了缓冲字符输入流,但是没有关闭文件字符流
提出场景
我们先不着急去解决这个问题,先提另外一个问题
A类中有m1方法 ,我想对m1方法进行扩展,怎么办?
小伙伴一定会迅速写出代码,继承,用多态的特性,直接上代码了
package src.main.java.com.Io.decker; /** * @author liuhuxiang * @version $Id: A.java, v 0.1 2018年06月01日 16:56 liuhuxiang Exp $ */ public class A { public void m1() { System.out.println("A--aMethod"); } }
package src.main.java.com.Io.decker; /** * @author liuhuxiang * @version $Id: B.java, v 0.1 2018年06月01日 16:56 liuhuxiang Exp $ */ public class B extends A{ public void m1(){ System.out.println("b---bMethod1"); super.m1(); System.out.println("b---bMethod2"); } }
package src.main.java.com.Io.decker; public class Test01 { public static void main(String[] args) { // 父类的引用指向子类的对象,换句话说,此时,B能够拿到父类A的引用 // a只能调用到A类中的方法,但是B继承于A,发生重写的时候(方法名完全一致的时候),会调用到B上 // 但是仅限于此,父类中其他方法,没有发生重写的,子类B调用不到 A a=new B(); a.m1(); } }
console b---bMethod1 A--aMethod b---bMethod2
好了,完成了,但是这样有个问题,耦合性太强了,A中m1修改的话,B也要修改,所以不推荐这样写,那怎么办,今天的主角登场,装饰者模式
装饰者模式
我们就以FileReader Bufferedreader为例子
package src.main.java.com.Io.decker; /** * 被装饰者 * @author liuhuxiang * @version $Id: FileReader.java, v 0.1 2018年06月01日 17:26 liuhuxiang Exp $ */ public class FileReader { public void close(){ System.out.println("FileReader----close"); } }
package src.main.java.com.Io.decker; /** * BufferedReader.close(),就不需要FileReader.close()(只需要关闭最外层的流) * 装饰者 * @author liuhuxiang * @version $Id: Bufferedreader.java, v 0.1 2018年06月01日 17:26 liuhuxiang Exp $ */ public class Bufferedreader { private FileReader fileReader; Bufferedreader(FileReader fileReader) { this.fileReader = fileReader; } public void close(){ System.out.println("----------扩展代码1--------"); fileReader.close(); System.out.println("----------扩展代码2--------"); } }
package src.main.java.com.Io.decker; /** * @author liuhuxiang * @version $Id: Test02.java, v 0.1 2018年06月01日 17:27 liuhuxiangExp $ */ public class Test02 { public static void main(String[] args) { //创建装饰者 FileReader fr = new FileReader(); //创建被装饰者 Bufferedreader bf = new Bufferedreader(fr); //执行完成我们发现,对FileReader进行了扩展 bf.close(); } }
console ----------扩展代码1-------- FileReader----close ----------扩展代码2--------
反思
这是后我们发现,原来在关闭BufferedReader的时候,FileReader就已经被关闭了,所以只要关闭最外层的流就可以了,这里用了一个装饰者模式