闲谈设计模式之接口隔离
接口隔离(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.
*
* <p> 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
* <em>mark</em> 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层中会做到尽量的细话每一个抽象。