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;

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

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作为成员变量(兄弟关系),而不是像上面的例子一样,通过继承(父子关系)

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

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 装饰者中必须要包含被装饰者

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

转载于:https://my.oschina.net/u/3523594/blog/1822732

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值