首页/开发/代码质量与评审速查/接口隔离原则 ISP(Interface Segregation Principle)
设计原则与模式62 条

接口隔离原则 ISP(Interface Segregation Principle)

客户不应被迫依赖它们不使用的接口(Martin 表述):大而全的接口拆成面向调用者的细接口,实现类不必为空方法占位,调用方依赖面收窄。

接口隔离原则是什么

接口隔离原则(ISP)要求客户不应被迫依赖它们不使用的接口:把大而全的接口按调用方视角拆成若干角色接口,实现类不必用空方法或抛异常来占位,调用方的依赖面也随之收窄。它关注的是调用方的依赖视图,而不是实现内部的职责划分。

基本信息

问题形态胖接口加上空实现或抛异常的占位方法
做法按使用方视角拆分角色接口
收益依赖更少,实现类负担更轻
与 SRP 的差别SRP 管修改原因,ISP 管调用方的依赖视图

典型使用场景

  • 一个接口被多个调用方共用:各方其实只用到其中一部分方法
  • 实现类被迫写空方法:说明接口对这类实现并不适用
  • 测试替身实现困难:接口太大,桩件要覆盖大量用不到的方法
  • 公共 API 演进:拆成角色接口之后各自独立变化
  • 依赖装配复杂:细接口让装配关系一眼看清

怎么找到角色边界

  • 从每个调用方出发,列出它实际用到的方法
  • 把交集之外的方法分出去,形成新的接口
  • 让实现类按需实现多个接口
  • 公共的基础方法可以放进更小的共享接口

角色接口示例

角色接口示例
// 之前:Worker 声明 work 与 eat,机器人被迫实现空的 eat
// 之后:按调用方视角拆开
interface Workable { void work(); }
interface Feedable { void eat(); }

class Robot implements Workable { public void work() { ... } }

拆分前后的差别

维度胖接口角色接口
实现负担被迫实现用不到的方法只实现需要的方法
依赖面调用方依赖全部方法只依赖用到的那部分
测试替身需要覆盖大量空方法只需实现少量方法
与 SRP 的差别值得记住:SRP 关心实现因为什么原因需要修改,ISP 关心调用方因为什么依赖而被牵连。
判断依赖是否过宽的方法很简单:看调用方实际调用了接口里的几个方法,用不到的部分就是多余的依赖。
拆分的前提是实现方确实存在差异;如果所有实现都用得上全部方法,那么现在的接口就是合适的。
公共 API 频繁拆接口:版本兼容负担会随拆分次数不断增长,需要先定发布策略。

易错点

  • 接口拆得像参数表:角色边界丢失,拼装成本反而上升
  • 公共 API 频繁拆接口:版本兼容负担随拆分次数增长
  • 用空实现应付胖接口:调用方一调用就抛异常,问题被推迟到运行时
  • 把 ISP 理解为一律拆小:接口太小会让装配与阅读成本一起上升
  • 在领域层按技术维度拆接口:角色边界与业务视角脱节,调用方仍要拼凑多个接口

数据来源与参考

  • Robert C. Martin · ISP 论述(《敏捷软件开发》等)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌