接口隔离原则英文全称是Interface Segregation Principle,缩写是ISP。
ISP的定义是:客户端不应该依赖它不需要的接口。另一种定义是:类间的依赖关系应该建立在最小的接口上。接口隔离原则将非常庞大、臃肿的接口拆分成更小具体的接口,这样客户讲会只需要知道他们感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。
接口隔离原则说白了就是,让客户端依赖的接口尽可能的小,这样说可能还有点抽象,我们一一个示例来说明一下。在此之前我们来说一个场景,在Java6以及之前的JDK版本中,有一个非常讨厌的问题,那就是在使用了OutputStream或者其他可关闭的对象之后,我们必须保证它们最终被关闭了,我们的SD卡缓存类中就有这样的代码:
/**
* 将图片存入SD卡中
* @param url
* @param bitmap
*/
public void put(String url,Bitmap bitmap) {
FileOutputStream out = null;
try {
out = new FileOutputStream(CACHE_DIR + url);
bitmap.compress(Bitmap.CompressFormat.PNG,100,out);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这段代码的可读性非常差,各种try...catch嵌套的都是简单的代码,但是会严重影响代码的可读性,并且多层级的大括号很容易将代码写到错误的层级中。我们对这类代码也非常反感,下面来看看如何解决这类问题。
我们可能知道Java中有一个Closeable接口,该接口标识了一个可关闭的对象,它只有一个close方法,我们要讲的FileOutputStream类就实现类就实现了这个接口,实际上还有100多个类实现了这还接口,这意味着,在关闭着100多个类型的对象时,都需要写出像put方法中finally代码段那样的代码。这是非常让人痛苦的,所以我们要把这个问题变得简单,既然都是实现了Closeable接口,那只要我建一个方法统一来关闭这些对象不就可以了吗,于是我们开始写下如下的工具类:
public class CloseUtils {
/**
*关闭Closeable对象
**/
public static void closeQuietly(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我们看看把这段代码运用到上述的put方法中的效果如何:
public void put(String url,Bitmap bitmap) {
FileOutputStream out = null;
try {
out = new FileOutputStream(CACHE_DIR + url);
bitmap.compress(Bitmap.CompressFormat.PNG,100,out);
} catch (Exception e) {
e.printStackTrace();
} finally {
CloseUtils.closeQuietly(out);
}
}
代码简洁了很多,而且这个工具类可以运用到各类可关闭的对象中,保证了代码的重用性。
CloseUtils的closeQuitely方法的基本原理就是依赖于Closeable抽象而不是具体实现(这不是依赖倒置原则么?),并且建立在最小化依赖原则的基础上,它只需要知道这个对象是可关闭的,其他的一概不关心,也就是这里所介绍的接口隔离原则。
优点:
- 降低耦合性
- 提高代码的可读性
- 隐藏实现细节