闲谈设计模式之接口隔离

闲谈设计模式之接口隔离

  • 接口隔离(Interface Segregation Principles)
    • 示例代码分析
      • 结合Android源码设计示例代码分
      • 对JavaIO层FileOutputStream的探讨

接口隔离(Interface Segregation Principles)

接口隔离:俗称ISP,其遵循原则就是,类之间的依赖建立在最小接口依赖上,减少不必要的接口,避免接口功能繁重冗余;分割成更小更具体的细化接口。

示例代码分析

结合Android源码设计示例代码分

public class DiskCache implements ImageCache {
    private String filePath = "";
    @Override
    public void put(String url, Bitmap bitmap) {
        //这里写下载图片写入本地图片缓存
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(filePath+url);
            bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

这一段存储文件的代码,看着没有什么问题,但是使用了过多的try catch的代码使得代码很臃肿,熟悉JavaIo的同学,应该会知道JavaIO有一个接口叫做Closeable这样一个接口,他负责了javaIO流关闭的一个抽象接口,通过利用这样一个接口就可以这样去写:

public class CloseTools {

    private CloseTools() { }

    private static class CloseToolsLazy{
        private static final CloseTools tools = new CloseTools();
    }

    public static CloseTools getInstance(){
        return CloseToolsLazy.tools;
    }

    public void close(Closeable closeable){
        if (closeable!=null){
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class DiskCache implements ImageCache {
    private String filePath = "";
    @Override
    public void put(String url, Bitmap bitmap) {
        //这里写下载图片写入本地图片缓存
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(filePath+url);
            bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

利用这样一个Closeable 接口,结合单例以及里氏替换原则去优化我们对流关闭的这样一个操作,那为什么说它是符合接口隔离呢,在JavaIO层次上不只有关闭这样一个还有flush等等操作,如果写了一个base接口里面这些IO抽象接口都在这里面,那你可以想象得到每一个IO的具体实现都要实例一些不相干的接口,那么对类的设计来说就是一场灾难。接下来以FileOutputStream源码进行分析。

对JavaIO层FileOutputStream的探讨

先来看一段相关源码:

public class FileOutputStream extends OutputStream{

}

public abstract class OutputStream implements Closeable, Flushable {
    public void flush() throws IOException {
    }

    public void close() throws IOException {
    }
}

public interface Closeable extends AutoCloseable {

    /**
     * Closes this stream and releases any system resources associated
     * with it. If the stream is already closed then invoking this
     * method has no effect.
     *
     * 

As noted in {@link AutoCloseable#close()}, cases where the * close may fail require careful attention. It is strongly advised * to relinquish the underlying resources and to internally * mark the {@code Closeable} as closed, prior to throwing * the {@code IOException}. * * @throws IOException if an I/O error occurs */ public void close() throws IOException; } public interface Flushable { /** * Flushes this stream by writing any buffered output to the underlying * stream. * * @throws IOException If an I/O error occurs */ void flush() throws IOException; }

结合部分源码可以得出一组UML类图:

在OutputStream 中flush以及close都是一个空方法,而FileOutputStream则负责实例化他们,为什么Flushable以及Closeable很贴切ISP原则呢?在有些IO流中,有些只需要关注某一个抽象,就像Closeable每一个流基本都会用到,而Flushable则不一定会用到,那么他们两个如果集合到一个接口中去呢?一些不需要用到Flushable接口的IO但是需要Closeable,是不是都要实例化Flushable?所以在JavaIO层中会做到尽量的细话每一个抽象。

你可能感兴趣的:(java设计模式,kotlin设计模式,设计模式)