在SOLID中,SRP和ISP有什么区别? (单一责任原则和界面隔离原则)

时间:2013-01-17 21:20:33

标签: oop design-patterns solid-principles single-responsibility-principle interface-segregation-principle

SOLID“界面隔离原则”与“单一责任原则”有何不同?

维基百科entry for SOLID says

  

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

然而,对我而言,这听起来只是将SRP应用于接口和类。毕竟,如果一个界面只负责一个概念性的东西,那么你将无法进一步分解它。

我是否遗漏了某些东西,或者是SR与SRP有多余?如果没有,那么ISP意味着SRP没有?

4 个答案:

答案 0 :(得分:30)

SRP告诉我们,您应该只对模块承担一项责任。

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

更具体地说,直截了当,他们对同一个想法有不同的看法 - SRP更侧重于设计师方面的观点,而ISP则更关注客户端点 - 观点。所以你基本上是对的。

一切都来自

  

ISP最初是由Robert C. Martin在使用时制定的   一些咨询施乐。施乐创建了一个新的打印机系统   可以执行各种任务,如装订一组打印纸   和传真。该系统的软件是从地面创建的   up并成功完成任务。随着软件的发展,制作   修改变得越来越困难,即使是最小的   改变将需要一个重新部署周期。这就是它   几乎不可能继续发展。设计问题是   几乎所有的任务都使用了一个主要的Job类。任何时候a   打印工作或装订工作必须完成,有人打电话给某些人   Job类中的方法。这导致了一个庞大或“胖”的课程   多种特定于各种不同客户的方法。   由于这种设计,主要工作将了解所有方法   打印作业,即使它们没用。

所以

  

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

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

答案 1 :(得分:9)

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

另一方面,ISP关注的是如何使用模块,是否仅仅消耗模块的一部分是有意义的,而忽略了某些方面。

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

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

答案 2 :(得分:5)

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

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

  1. 违反SRP会对整个设计结构产生深远影响,导致可维护性差,重复使用,当然还有低内聚和耦合。
  2. SRP对对象结构的行为和结构组件都有影响。
  3. 重新设计SRP违规需要更深入的分析,需要以整体方式查看设计的不同组成部分。
  4. 违反ISP的主要原因是可读性差(在某种程度上,内聚力低)。但是对维护和代码重用的影响远没有SRP那么险恶。

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

    另请参阅我的博客SRPISP

答案 3 :(得分:1)

Robert Martin tweeted于2018年5月16日发布。

  可以将

ISP视为类似于接口的SRP。但不仅限于此。 ISP概括为:“不要依赖超出您的需求。” SRP概括为“将由于相同原因和相同时间而发生的变化汇集在一起​​。”

     

想象一下同时具有push和pop的堆栈类。想象一个只推的客户。如果该客户端取决于堆栈接口,则取决于不需要的pop。 SRP不会将推送与弹出分开。 ISP就可以。