2013-01-17 119 views
31

SOLID“界面分离原则”与“单一责任原则”有何区别?在SOLID中,SRP和ISP之间有什么区别? (单一职责原则和界面分离原则)

维基百科entry for SOLID says

ISP分裂,这是非常大的成更小和更具体的那些接口,以便用户将只需要知道这是他们感兴趣的

方法然而,对我来说,这听起来像是将SRP应用于接口以及类。毕竟,如果一个接口只负责一个概念性的事情,那么你将无法进一步细分。

我错过了什么,或者是与SRP冗余的ISP?如果不是,那么ISP意味着SRP不是什么?

+0

可能的复制的http://stackoverflow.com/questions/8099010/is-interface-segregation-principle-only-a-substitue-for-single-responsibility- pr –

+0

我想在技术上,但这个问题是恕我直言,写得更好,答案更充实。 – ArtB

回答

25

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

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

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

这一切都来自

附带的ISP首次使用了和罗伯特C.马丁制定做 一些咨询施乐时。施乐创建了一个新的打印机系统, 可以执行各种任务,如装订一套打印纸张 和传真。该系统的软件是从地面 开始创建并成功完成其任务。随着软件的增长,对 进行修改变得越来越困难,因此即使是最小的更改也需要一个小时的重新部署周期。这使得它几乎不可能继续发展。设计问题是几乎所有任务都使用了一个主要的Job类。任何时候必须完成打印作业或装订作业,都会在Job类中调用一些 方法。这导致了一个巨大的或“胖”的类与 众多方法特定于各种不同的客户端。 由于这种设计,一个主要作业会知道打印作业的所有方法 ,即使它们没有用处。

所以

由马丁提出的解决方案是所谓的接口 今天隔离原则。应用于施乐软件,使用依赖反转原理将Job类与其所有客户端之间的一层接口添加到 。作业类不是一个大的作业类,而是创建一个装订作业界面或一个打印作业界面 ,主要用于装订或打印类, 调用作业类的方法。因此,为每个作业创建了一个接口 ,这些接口全部由Job类实现。

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

+1

嗯,我从你的帖子看到的唯一区别是''如果你想从界面I中使用print()方法,你不应该为此实例化一个SwimmingPool或DriveThru类。“'''''很多都喜欢“[你想要一根香蕉,但你得到的是一只持有香蕉和整个丛林的大猩猩。](http://www.johndcook.com/blog/2011/07/19/you-wanted-banana/) ”。你是说香蕉评论是ISP的一个解释吗? – ArtB

+0

这是正确的。 –

+0

您经常会看到设计得不好的代码,在使用某些功能时,您必须首先打开日志记录,然后打开A,B和C服务,而您只需要计算省略号的区域即可是你所期待的不需要的东西。 –

5

SRP关注的是什么模块会,以及它是如何做,不允许的抽象级别的任意组合。基本上,只要一个组件可以用一个句子广泛定义,它就不会破坏SRP。另一方面,ISP关心的是如何消费一个模块,是否仅仅消费模块的一部分是有意义的,而忽略某些方面。

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

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

4

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

但是在其他方面还是有差异的。

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

违反互联网服务提供商主要是差的可读性(并在一定程度上,低凝聚力)。但是对维护和代码重用的影响远没有SRP那么严重。此外,重构代码到ISP构造,似乎只是一个结构性变化。

参见我的博客SRPISP

+0

我已经开始采取的一点是,SRP是域中的一个责任,而ISP是单一的行为。因此,在一个拥有'Book'类的类和'Movie'类的类库是一个SRP,但是'getDueDate()'和'getMexRenewal()'是它们自己的接口(例如'Rentable')'getId ()'(例如'Identifiable')是ISP,即使所有的'Rentable'类都是'Identifiable'。这几乎与“原子”或“分离”的定义对于接口而言不同于类的定义一样。 – ArtB

+0

“原子”或“分离”没有正式的定义。在这方面,构建类的设计考虑因素与界面相同。 – aknon

+0

说接口方法为实现类定义责任是否是错误的?它必须是,否则在实现的类中有一些接口有一个'NIL'实现的重写方法。放入你的话,接口方法(放在一起)定义了一种类型的“原子”行为。类的“原子”行为,或所谓的“责任”是许多这样的行为的总和。 (当然,对于非最终类,所有公共方法必须可以用不同的实现来替代) – aknon