声明:本系列博客整理来源于《Android源码设计模式解析与实战》,仅作为个人学习总结记录,任何组织和个人不得转载进行商业活动!
接口隔离原则(Interface Segregation Principle,ISP)
ISP的定义是:客户端不应该依赖它不需要的接口。另一种定义是:类间的依赖关系应该建立在最小的接口上。接口隔离原则将非常庞大、臃肿的接口拆分成更小的和更具体的接口,这样客户将会只需要知道他们感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。
在Java6以及之前的JDK版本,在使用了OutputStream或者其他可关闭的对象之后,我们必须保证它们最终被关闭了,在SD缓存类中有这样的代码:
//将图片缓存到内存中
public void put(String url,Bitmap bitmap){
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(cacheDir+url);
bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream)
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} // end if
} // end if finally
}
我们看到的这段代码可读性非常差,各种try...catch嵌套都是些简单的代码,但是会严重影响代码的可读性,并且多层级的大括号很容易将代码写到错误的层级中。大家应该对这类代码也非常反感,那我们看看该如何解决这类问题。
我们可能知道Java中有一个Closeable接口,该接口标识了一个可关闭的对象,它只有一个close方法,如下所示:

其中FileOutputStream类就实现了这个接口。从图中我们可以看到,还有100多个类实现了Closeable这个接口,这意味着,在关闭这100多个类型的对象时,都需要写出像put方法中finally代码段那样的代码。所以,需要进行优化做法,小民想到解决问题的方法,既然都是实现了Closeable接口,就建一个方法来统一关闭这些对象,使用工具类:
public final class CloseUtils {
private CloseUtils(){}
/**
* 关闭Closeable对象
* @param closeable
*/
public static void closeQuitely(Closeable closeable){
if(closeable != null){
try {
closeable.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
然后,将这个工具类应用到上面的put方法中:
//将图片缓存到内存中
public void put(String url,Bitmap bitmap){
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(cacheDir+url);
bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
CloseUtils.closeQuitely(fileOutputStream);
}
}
这样可以看到,代码简洁了很多!而且这个closeQuietly方法可以运用到各类可关闭的对象中,保证了代码的重用性。CloseUtils的closeQuietly方法的基本原理就是依赖于Closeable抽象而不是具体实现,这正满足了依赖倒置原则,并且建立在最小化依赖原则的基础上,它只需要知道这个对象是可关闭的,其他的一概不用关心,这也是接口隔离原则。
试想一下,如果在只是需要关闭一个对象时,它却暴露出了其他的接口函数,如OutputStream的write方法,这就使得更多的细节暴露在客户端代码面前,不仅没有很好地隐藏实现,还增加了接口的使用难度。而通过Closeable接口将可关闭的对象抽象起来,这样只需要客户端依赖于Classable就可以对客户端隐藏其他的接口信息,客户端代码只需要知道这个对象可关闭(只可调用close方法)即可。小民设计的ImageLoader中的ImageCache就是接口隔离原则的运用,ImageLoader只需要知道该缓存对象有存、取缓存图片的接口即可,其他的一概不管,这就使得缓存功能的具体实现对ImageLoader隐藏。这就是最小化接口隔离了实现类的细节,也促使我们将庞大的接口拆分到更细粒度的接口当中,这使得我们的系统具有更低的耦合性,更高的灵活性。
Bob大叔(Robert C Martin)在21世纪早期将单一职责、开闭原则、里氏替换、接口隔离以及依赖倒置5个原则定义为SOLID原则,作为面向对象编程的5个基本原则。当这些原则被一起使用时,它们使得软件系统更清晰、简单,最大程度地拥抱变化。SOLID被典型地应用在软件驱动开发上,并且是敏捷开发以及自适应软件开发基本原则的重要组成部分。在通过这前五个原则的学习之后,我们发现这几大原则最终就可以化为这个关键词:抽象、单一职责、最小化。那么,在实际开发中如何权衡、实践这些原则,大家需要在实践中多思考与领悟,正所谓“学而不思则罔,思而不学则怠”,只有不断地学习、实践、思考,才能够在积累的过程中有一个质的飞跃。
本文探讨了接口隔离原则(ISP)在Java编程中的应用,通过优化关闭资源的代码示例,介绍了CloseUtils工具类的设计思路,展示了如何遵循ISP原则减少代码耦合,提高系统灵活性。
3946





