接口隔离原则,ISP,Interface Segregation Principle
用于处理胖接口(fat interface)所带来的问题。如果类的接口定义暴露了过多的行为,则说明这个类的接口定义内聚程度不够好
第一种定义: Clients should not beforced to depend upon interfaces that they don't use.
客户端不应该依赖它不需用的接口
第二种定义:The dependency of oneclass to another one should depend on the smallest possible interface。
类间的依赖关系应该建立在最小的接口上
ISP还是比较简单的,通过行为分离,达到高内聚效果
不遵循ISP
类A依赖接口I中的方法1、方法2、方法3,类B是对类A依赖的实现。类C依赖接口I中的方法1、方法4、方法5,类D是对类C依赖的实现。
对于类B和类D来说,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但由于实现了接口I,所以也必须要实现这些用不到的方法
显然接口I是个胖接口,客户端依赖了他不需要用的接口方法
遵循ISP
将原有的接口I拆分为三个接口,类A不需要用到“方法4”和“方法5”,就可以选择不依赖接口I3
实例
设计一个门接口,它包含了一款自动门所需要的功能,开关,自动关闭等。
但是并不是每个门都有自动关闭的功能,所以timeOut超时这个方法放在该接口中,就会导致所有实现这个接口的子类都会默认的继承了这个方法,哪怕子类中不对这个方法做处理。
把接口拆分成2个,拆分成Door和TimeClient,2个接口,这样Door就只保持原有的基本功能,而timeOut超时的方法则放到TimeClient接口中,这样就可以解决上述中接口臃肿的问题
VS SRP
很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然
其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。
其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建
在单一职责原则中,一个接口可能有多个方法,提供给多种不同的调用者所调用,但是它们始终完成同一种功能,因此它们符合单一职责原则,却不符合接口隔离原则,因为这个接口存在着多种角色,因此可以拆分成更多的子接口,以供不同的调用者所调用。
比如说,项目中我们通常有一个Web服务管理的类,接口定义中,我们可能会将所有模块的数据调用方法都在接口中进行定义,因为它们都完成的是同一种功能:和服务器进行数据交互;但是对于具体的业务功能模块来说,其他模块的数据调用方法它们从来不会使用,因此不符合接口隔离原则
架构
在一般情况下,任何层次的软件设计如果依赖于不需要的东西,都会是有害。
从源代码层次来说,这亲的依赖关系会导致不必要的重新编译和重新部署
对更高层次的软件架构设计来说,问题也类似
如果D中包含了F不需要的功能,那么这些功能同样也会是S不需要的。对D中这些功能的修改会导致F需要被重新部署,后者又会导致S的重新部署。
更糟糕的是,D中一个无关功能的错误也可能会导致F和S运行出错
TIPS
采用接口隔离原则对接口进行约束时,要注意以下几点:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则
Reference
《整洁架构之道》
Interface Segregation Principle(ISP)--接口隔离原则