64

SOLID “接口隔离原则”与“单一职责原则”有何不同?

SOLID的维基百科条目说

ISP 将非常大的接口拆分为更小、更具体的接口,以便客户端只需了解他们感兴趣的方法

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

我错过了什么,还是 ISP 与 SRP 有点多余?如果不是,那么 ISP 暗示 SRP 没有什么?

4

4 回答 4

43

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

ISP 告诉我们,您不应该被迫面对超出您实际需要的东西。如果您想使用print()interface 中的方法I,则不必为此实例化 aSwimmingPoolDriveThru类。

更具体地说,直截了当,它们是对同一想法的不同看法——SRP 更关注设计者的观点,而 ISP 更关注客户端的观点. 所以你基本上是对的。

这一切都来自

ISP 最初是由 Robert C. Martin 在为 Xerox 做一些咨询时使用和制定的。施乐创建了一个新的打印机系统,可以执行各种任务,例如装订一组打印的文件和传真。该系统的软件是从头开始创建并成功执行其任务的。随着软件的发展,修改变得越来越困难,以至于即使是最小的更改也需要重新部署周期到一个小时。这使得继续开发几乎不可能。设计问题是几乎所有任务都使用一个主要的 Job 类。每当必须完成打印作业或装订作业时,都会调用 Job 类中的某个方法。这导致了一个巨大的或“胖”类,其中包含多种特定于各种不同客户端的方法。

所以

Martin 提出的解决方案就是今天所谓的接口隔离原则。应用于 Xerox 软件,使用依赖倒置原则在 Job 类与其所有客户端之间添加了一层接口。没有一个大的 Job 类,而是创建了 Staple Job 接口或 Print Job 接口,分别由 Staple 或 Print 类使用,调用 Job 类的方法。因此,为每个作业创建了一个接口,这些接口都是由 Job 类实现的。

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

于 2013-01-17T21:24:12.210 回答
19

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

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

保持精神或 SRP 但可以破坏 ISP 的代码示例是外观模式。它有一个单一的职责,“提供对更大子系统的简化访问”,但如果底层子系统需要公开截然不同的想法,它确实会破坏 ISP。

也就是说,通常当一段代码破坏了 SOLID 原则时,它通常会破坏整个代码。打破特定原则而保留其余原则的具体例子在野外很少见。

于 2013-01-17T21:39:02.847 回答
11

罗伯特·马丁于 2018 年 5 月 16 日发布了以下推文。

对于接口,ISP 可以看作类似于 SRP;但不仅如此。ISP 概括为:“不要依赖于你需要的东西。” SRP 概括为“将因相同原因在同一时间发生变化的事物聚集在一起。”</p>

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

于 2019-03-09T01:06:44.603 回答
5

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

但是,在其他方面存在差异。

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

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

此外,将代码重构为 ISP 构造,似乎只是一种结构上的改变。

另请参阅我的博客以了解SRPISP

于 2013-12-18T10:50:02.517 回答