- 贯穿设计模式:用一个电商项目详解设计模式
- 伟山育琪
- 1344字
- 2024-12-28 11:44:54
1.2.2 接口隔离原则
对于接口隔离原则(Interface Segregation Principle,IPS),单从“隔离”这个字眼来说,我们很容易错误地理解接口隔离原则。因为接口“隔离”意味着接口“划分”,那么“划分”是不是就是指职责划分?职责划分是不是就是指上一小节所叙述的“单一职责原则”?
其实,单一职责原则是接口隔离原则的基础,单一职责原则注重职责的划分,从职责角度进行类和接口的划分;在此基础上,接口隔离原则登场,注重接口使用的“精确性”和“最小化”。如果读者依然没有理解两者的区别和关系,请不要着急,可以继续往下阅读,我会以JDK源码为例,为读者进行更明确的解释。接口隔离原则,主要体现在以下两个方面。
(1)不要使用没有任何依赖关系的接口。
肯定有读者会认为这是一句空话,而且这句话还泛着一点傻气。正常开发过程中,如果不依赖某个接口,肯定是没有人使用的,但是随着业务代码的累加,也难免会出现这样的问题,即使是JDK中数据结构源码的作者,也依然在不经意间使用了无须使用的接口。接下来我们对JDK源码的阐述,纯粹从技术角度进行展开。
我们先来看下以下代码执行逻辑。
当我们执行这个main函数的时候,会收到以下报错信息。
从以上的报错信息我们能够清楚看到,是add方法发生了异常,因为Collections通过emptyList()方法创建的空集合,是不能够进行元素添加的。可是,当我们跳转到源码看EmptyList的类结构时,却发现了RandomAccess接口的存在,而RandomAccess接口真的不应该出现,它是一个无用的接口实现。
为什么说上边源码中的RandomAccess是无用的接口实现呢?大部分读者可能都知道,RandomAccess接口是一个标志接口(Marker),只要类List集合实现这个接口,就能支持快速随机访问。可是当前的EmptyList,从对象的创建到灭亡,都不会有任何元素的添加,没有元素又何谈元素的快速随机访问呢?
如果单从接口隔离原则上来讲,这个RandomAccess接口,完全没有存在的必要,这是源码作者的一个疏忽。当然,此处的RandomAccess的使用,也可能是为了后续对EmptyList对象的扩展,支持元素添加功能,只需要实现父类AbstractList中的add方法即可,那么RandomAccess也就自然有了它的用武之地。
我们继续分析,这部分源码首先遵循了单一职责原则,RandomAccess作为快速随机访问的标志类,就是一个明确的职责划分,符合单一职责原则;而接口隔离原则在此处的作用是告诉大家:RandomAccess当用时则用,不当用时勿用。
(2)一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。如果将没有关系的接口合并在一起,形成一个臃肿的大接口,那并不是一个好的设计,违背了接口隔离原则。我们以JDK的ArrayList源码设计进行说明,体会接口隔离原则的意义。我们来看以下ArrayList类结构:
从上边的类结构代码中能够很明显地看到,ArrayList有四种特质:
①集合特质:因为实现了List接口。
②快速随机访问:因为实现了RandomAccess接口。
③支持克隆:因为实现了Cloneable接口。
④支持序列化:因为实现了Serializable接口。
这样的类结构,首先是遵循了单一职责原则,按职责划分为不同的接口;然后在此基础上,接口隔离原则登场,细化接口的方法,保持接口的纯洁性,在满足需求的前提下,尽量减少接口的方法,做到专业、精确、最小化接口。
当然,我们平时工作过程中,已经不知不觉中遵循了接口隔离原则,不使用没有依赖关系的接口、接口细化、剔除无用方法等,都是接口隔离原则很好的实践。还是那句话,一切都应该以项目实际情况为出发点进行设计,因地制宜才是我们真正需要遵守的原则。