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

提出问题

今天在coding的时候发现了个问题,使用流的时候,处理流会包装一个节点流,可是在流关闭的时候,咱们只须要关闭处理流(最外层的流),被包装的节点流都不关闭,这是怎么回事呢,咱们以FileReader 和BufferedReader为例子java

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();
    }
}

上面代码咱们发现,只关闭了缓冲字符输入流,可是没有关闭文件字符流this

提出场景

咱们先不着急去解决这个问题,先提另一个问题spa

A类中有m1方法 ,我想对m1方法进行扩展,怎么办?对象

小伙伴必定会迅速写出代码,继承,用多态的特性,直接上代码了继承

package src.main.java.com.Io.decker;

public class A {
    public void m1() {
        System.out.println("A--aMethod");
    }
}
package src.main.java.com.Io.decker;


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为例子it

package src.main.java.com.Io.decker;
/**
 * 被装饰者
 */
public class FileReader {
    public void close(){
        System.out.println("FileReader----close");
    }
}
package src.main.java.com.Io.decker;
/**
 * BufferedReader.close(),就不须要FileReader.close()(只须要关闭最外层的流)
 * 装饰者
 */
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--------");
    }
}

这里是吧FileReader做为成员变量(兄弟关系),而不是像上面的例子同样,经过继承(父子关系)io

这样的话,即使FileReader里面有改动,仍然不影响Bufferedreaderconsole

package src.main.java.com.Io.decker;
/**
 */
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--------

装饰者模式的要求

1 装饰者中必需要包含被装饰者class

2 装饰者模式的要求,装饰者和被装饰者必需要实现同一个接口或者类型

如上面的例子,都有close(),那么咱们对代码进行改造下,提出一个抽象方法,被装饰者和装饰者分别继承

public abstract class Reader {
    public abstract void close();
}
public class FileReader  extends  Reader {
    public void close(){
        System.out.println("FileReader----close");
    }
}
public class Bufferedreader  extends Reader{
    private Reader reader;
    Bufferedreader(Reader reader) { // 这里是个多态 Reader reader=new FileReader();
        this.reader = reader;
    }
    public void close(){
        System.out.println("----------扩展代码1--------");
        reader.close();
        System.out.println("----------扩展代码2--------");
    }
}

这样的话就知足了装饰者模式的要求,并且Bufferedreader和FileReader 的关系就不大了,由于在Bufferedreader里面,成员变量不是一个具体的类型,是一个抽象类

public class Test02 {
    public static void main(String[] args) {
        FileReader fr = new FileReader();
        Bufferedreader bf = new Bufferedreader(fr);
        bf.close();
    }
}

反思

这是后咱们发现,原来在关闭BufferedReader的时候,FileReader就已经被关闭了,因此只要关闭最外层的流就能够了,这里用了一个装饰者模式

相关文章
相关标签/搜索