BufferedReader.close()引发的对装饰者模式的思考

提出问题

今天在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就已经被关闭了,所以只要关闭最外层的流就可以了,这里用了一个装饰者模式

猜你喜欢

转载自my.oschina.net/u/3523594/blog/1822732