IO中用到那些设计模式

装饰器模式

IO中有一个著名的缓冲流就是基于装饰者模式实现的,他的实现方式很简单,如下图,BufferedInputStream继承FilterInputStream,而FilterInputStream和其他需要InputStream类同级,所以当其他同级InputStream需要使用缓冲流加强时,只需要将这个类作为参数传入缓冲流即可。

装饰者模式的类图如下:

ios 如何选择设计模式 io的设计模式_设计模式

代码示例

@Test
    public void decoratorTest()throws Exception{
        BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream("input.txt"));
    }

适配器模式

在介绍IO流中的适配器模式前,我们需要了解一下适配器模式的两种形式,对象适配和类适配器

对象适配

如下图所示,我们希望Something类拥有Target类的行为,我们就可以编写一个适配器,将Something组合到适配器中,然后继承Target接口,用Something做实现即可。

通俗的理解就是接口的方法用我们聚合的类的方法实现。

ios 如何选择设计模式 io的设计模式_ios 如何选择设计模式_02

代码示例:

Target

package com.guide.io.designParttern.adapt;

public interface Target {
    void method1();
    void method2();
    void method3();
}

Something

public class Something {
    public void method2() {
        System.out.println("Something method2");
    }

    public void method3() {
        System.out.println("Something method3");
    }
}

SomeAdapter

public class SomeAdapter implements Target {

    /**
     * 用组合关系添加一个something完成转Target的适配
     */
    private Something something;

    public SomeAdapter(Something something) {
        this.something = something;
    }

    @Override
    public void method1() {
        something.method2();
    }

    @Override
    public void method2() {
        something.method2();
    }

    @Override
    public void method3() {
        something.method3();
    }
}

类适配器模式

如下图,Something类向拥有Target的行为我们就编写一个适配器,继承Something、Target,用Target方法封装Something

ios 如何选择设计模式 io的设计模式_ios 如何选择设计模式_03

适配代码如下所示

public class SomeAdapter2 extends Something implements Target {

    /**
     * 用Something作为Target的实现从而完成适配
     */
    @Override
    public void method1() {
        method2();
    }
    
    
}

而我们的IO则是用我们前面所说的对象适配器,使用InputStreamReader实现InputStream转为BufferedReader

@Test
    public void adapterTest() throws FileNotFoundException {
        //适配器模式 对象适配模式
        BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream("")));
    }

查看源码如下所示

//将InputStream 作为参数传入作为构造参数,完成转换适配

public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }

工厂模式

FilesnewInputStream 就是用静态工厂模式,代码使用示例如下

InputStream is Files.newInputStream(Paths.get(generatorLogoPath))

查看源码就会发现有个provider根据用户传入参数返回输入流:

public static InputStream newInputStream(Path path, OpenOption... options)
        throws IOException
    {
        return provider(path).newInputStream(path, options);
    }

观察者模式

NIO 中的Watchable使用到了观察者模式。代码如下所示,可以看到调用者只需将感兴趣监控事件WatchService 以及回调事件events都作为参数传入即可完成事件的观察和响应。

public interface Watchable {


    WatchKey register(WatchService watcher,
                      WatchEvent.Kind<?>[] events,
                      WatchEvent.Modifier... modifiers)
        throws IOException;



    WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events)
        throws IOException;
}

参考文献

Java IO设计模式总结

Java IO模型详解

Java设计模式-结构型-适配器模式

聊聊Netty那些事儿之从内核角度看IO模型