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

问题描述 投票:38回答:4

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

维基百科entry for SOLID says

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

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

我错过了什么,或者是SR与SRP有多余?如果没有,那么ISP是什么意味着SRP没有?

oop design-patterns solid-principles single-responsibility-principle interface-segregation-principle
4个回答
30
投票

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

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

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

这一切都来自

互联网服务提供商最初是由Robert C. Martin在为Xerox提供咨询时使用和制定的。施乐创建了一个新的打印机系统,可以执行各种任务,如装订一套打印纸和传真。该系统的软件是从头开始创建的,并成功完成了任务。随着软件的发展,修改变得越来越困难,即使是最小的改变也会将重新部署周期缩短到一个小时。这使得几乎不可能继续发展。设计问题是几乎所有任务都使用了一个主要的Job类。无论何时必须完成打印作业或装订作业,都会调用Job类中的某些方法。这导致了一个庞大或“胖”的课程,其中包含针对各种不同客户的多种方法。由于这种设计,主要作业将知道打印作业的所有方法,即使它们没有用处。

所以

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

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


9
投票

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

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

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

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


5
投票

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

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

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

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

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

另见我的博客SRPISP


1
投票

Robert Martin tweeted于2018年5月16日发布以下内容。

可以看出ISP与接口的SRP类似;但它不止于此。 ISP概括为:“不要依赖于你需要的东西。”SRP概括为“将出于同样原因和同时发生变化的事情聚集在一起”。

想象一下具有push和pop的堆栈类。想象一下只有推动的客户。如果该客户端依赖于堆栈接口,则它取决于pop,它不需要它。 SRP不会将推送与流行音乐分开; ISP会的。

© www.soinside.com 2019 - 2024. All rights reserved.