在 SOLID 中,SRP 和 ISP 之间的区别是什么? (单一责任原则和接口隔离原则)

很可靠的“接口隔离原则”与“单一责任原则”有何不同?

维基百科 SOLID 的条目显示

ISP 将非常大的接口分割成更小、更具体的接口,这样客户只需要知道他们感兴趣的方法

然而,对我来说,这听起来就像是将 SRP 应用于接口和类一样。毕竟,如果一个接口只负责一个概念上的事情,那么您将无法进一步分解它。

是我漏掉了什么,还是 ISP 和 SRP 有点多余?如果没有,那么 ISP 暗示 SRP 没有做什么?

10913 次浏览

SRP 告诉我们,在一个模块中您应该只有一个职责。

ISP 告诉我们,你不应该被迫面对超过你实际需要的东西。如果希望使用接口 I中的 print()方法,则不必为此实例化 SwimmingPoolDriveThru类。

更具体地说,直奔主题,他们在同一个想法上有不同的观点—— SRP 更关注设计者一方的观点,而 ISP 更关注客户一方的观点。所以你基本上是对的。

这一切都来自

ISP 最初是由罗伯特 · C · 马丁(RobertC.Martin)在进行 施乐公司创造了一种新的打印机系统 可以执行各种任务,如订一套印刷文件 和传真。这个系统的软件是从地面创建的 随着软件的不断发展, 修改变得越来越困难,以至于即使是最小的 改变将需要一个重新部署周期到一个小时。这是使它 几乎不可能继续开发。设计问题是 一个主要的 Job 类被几乎所有的任务使用 打印工作或订书机工作必须做,一个电话给一些 这导致了一个巨大的或“胖”的类 针对各种不同客户端的多种方法。 由于这种设计,订书钉作业将了解所有的方法 印刷工作,即使没有使用他们。

所以

Martin 提出的解决方案就是所谓的接口 今天的分离原理。应用于施乐软件,一层 添加了 Job 类与其所有客户端之间的接口 用依赖反转原则而不是一个大的 创建了作业类、 Staple 作业接口或打印作业接口 将分别由 Staple 或 Print 类使用, 调用 Job 类的方法。因此,创建了一个接口 对于每个作业,这些作业都是由 Job 类实现的。

@ http://en.wikipedia.org/wiki/Interface_segregation_principle#Origin

SRP 关心的是一个模块做什么以及如何做,不允许任何抽象级别的混合。基本上,只要一个组件可以用一个句子广泛地定义,它就不会破坏 SRP。

另一方面,ISP 关心的是如何使用模块,是否只使用模块的一部分,而忽略某些方面是有意义的。

作为保持精神或 SRP 但可以打破 ISP 的代码的一个例子,是 Facade 模式。它只有一个职责,“提供对更大子系统的简化访问”,但是如果底层子系统需要暴露大量不同的想法,它的确会破坏 ISP。

也就是说,通常当一段代码打破了 SOLID 原则,它往往会打破整个系统。具体的例子,打破了一个具体的原则,同时保存其余的在野外是罕见的。

SRP 和 ISP 最终归结为相同的东西。实现它们中的任何一个都需要分割类或接口。

然而,在其他方面也存在差异。

  1. 违反 SRP 会对整个设计结构产生深远的影响,导致可维护性差、重用性差,当然还有内聚性和耦合性差。
  2. SRP 对对象结构的行为组件和结构组件都有影响。
  3. 重新设计违反 SRP 需要更深入的分析,需要从整体上看待设计的不同组成部分。

违反 ISP 的主要原因是可读性差(在某种程度上,内聚力低)。但是对维护和代码重用的影响远没有 SRP 那么严重。

此外,重构代码到 ISP 构造,似乎只是一个结构性的变化。

也可以看看我的博客 SRP互联网服务供应商

罗伯特 · 马丁2018年5月16日。

ISP 可以被看作类似于接口的 SRP,但它不仅仅是这样。ISP 归纳为: “不要依赖超过你需要的东西。”SRP 概括为“收集因相同原因同时发生变化的事情”

想象一个同时具有 push 和 pop 的堆栈类。想象一下一个客户。如果客户端依赖于堆栈接口,那么它依赖于它不需要的 pop。SRP 不会将推送和流行分开; ISP 会。

根据我的理解,这两个原则是互补的,也就是说,它们需要结合起来。

违反 ISP 的最终后果是变得脆弱,“猎枪手术”或“蝴蝶效应”。许多代码可能会中断或需要代码更新,因为它们依赖于某些接口或对象,而这些接口或对象提供的内容超出了它们的需要。变化太大了。

违反 SRP 的后果主要是降低了可读性和维护性。由于缺乏清晰的代码结构,人们可能需要在整个代码库(单个职责过于分散)或单个大单元(多个职责挤在一起)中进行搜索,以便进行连贯的更改。通常,完全理解某些代码段的关注点(用途)会增加开销。改变被阻止了。

通过这种方式,这两个原则就像是理智的变更管理的下限和上限。

在没有 ISP 的情况下满足 RSP 的例子——正如其他答案所提供的那样——表明可以存在真正属于一起的代码(如引用 Robert C. Martin 的堆栈例子)。但它可能做得太多,是过度设计等。也许在非常小的示例中,这种效果是不可见的,但是如果它变大了,在(间接的)依赖关系中的一些不相关的部分被更改之后,依赖类仍然能够正确编译可能会更舒服。而不是因为不相关的事情被改变而不再编译。