26

接口隔离原则 (ISP) 说,许多特定于客户端的接口优于一个通用接口。为什么这很重要?

4

7 回答 7

34

ISP 声明:

不应强迫客户依赖他们不使用的方法。

ISP 涉及到重要的特性——内聚耦合
理想情况下,您的组件必须高度定制。它提高了代码的健壮性和可维护性。

执行 ISP 可为您带来以下好处:

  • 内聚- 更好的可理解性、鲁棒性
  • 耦合- 更好的可维护性,高抗更改性

如果您想了解有关软件设计原则的更多信息,请获取《敏捷软件开发、原则、模式和实践》一书的副本。

于 2008-09-12T13:45:54.407 回答
10

界面隔离是SOLID原则上的“我”,在深入第一个之前,让我们解释一下后者是什么意思。

SOLID 可以被认为是专家提出的一组最佳实践和建议(意味着它们已经被证明过),以便为我们如何设计应用程序提供可靠的基础。这些实践力求使我们的应用程序更易于维护、扩展、调整和扩展。

我为什么要关心 SOLID 编程?

首先,你必须意识到你不会永远在你所在的地方。如果我们使用标准和众所周知的架构,我们可以确定我们的代码将很容易被我们之后的其他开发人员维护,而且我相信您不会想要处理修复代码的任务'没有应用任何已知的方法,因为它很难理解。

接口隔离原则。

知道我们知道什么是 SOLID 原则,我们可以更详细地了解接口隔离原则,但是接口隔离到底说了什么?

“不应强迫客户实施他们不会使用的不必要的方法”</p>

这意味着有时我们倾向于使用很多方法来制作接口,这在一定程度上可能很好,但是这很容易被滥用,我们最终会得到实现空方法或无用方法的类,这当然会增加额外的代码和负担到我们的应用程序。想象一下,你在单个接口中声明了很多方法,如果你喜欢视觉辅助一个正在实现接口但确实需要几个方法的类,它看起来像这样:

在此处输入图像描述

另一方面,如果您正确应用接口隔离并将接口拆分为更小的子集,您可以确保实现那些只需要的:

在此处输入图像描述

看!好多了!执行此原则将使您具有低耦合性,这有助于更好的可维护性和对更改的高抵抗力。因此,您可以真正利用接口的使用并在真正需要的时候实现方法。现在让我们回顾一个不太抽象的示例,假设您声明了一个名为 Reportable 的接口

public interface Reportable {

        void printPDF();
        void printWord();
        void printExcel();
        void printPPT();
        void printHTML();


}

而且你有一个客户端,只导出Excel格式的一些数据,你可以实现接口,但你只需要实现excel方法吗?答案是否定的,即使您不打算使用它们,您也必须为所有方法编写实现代码,这可能会导致大量垃圾代码,从而使代码难以维护。

记住保持简单,不要重复自己,你会发现你已经在不知不觉中使用了这个原则。

于 2013-08-01T16:15:46.030 回答
5

它简化了任何一个客户端将使用的接口,并删除了他们可能在他们不需要的接口部分上开发的依赖项。

于 2008-09-12T13:47:05.167 回答
4

一个原因是,拥有许多接口,每个接口的方法数量最少,这样更容易实现每个接口并正确实现它们。一个大的界面可能是不守规矩的。此外,在场景中使用焦点接口使代码更易于维护,因为您可以看到正在使用对象的哪个方面(例如,IComparable 接口让您知道该对象仅用于给定场景中的比较)。

于 2008-09-12T17:07:35.403 回答
3

该原则主要用于双重目的

  • 使代码更具可读性和可管理性。

  • 促进对类的单一责任(高凝聚力)。当然,为什么一个类应该有一个对行为没有影响的方法?为什么不直接删除它。这就是 ISP 的意义所在

设计师必须向 ISP 提出一些问题

  • 用 ISP 实现什么
  • 如何分析任何 ISP 违规的现有代码

为了进一步讨论,我还必须补充一点,这个原则并不是最严格意义上的“原则”,因为在某些情况下,将 ISP 应用于设计,而不是提高可读性,可能会使对象结构变得不可读和混乱不必要的代码。您可能会在 java.awt.event 包中观察到这一点

更多在我的博客:http ://design-principle-pattern.blogspot.in/2013/12/interface-segregation-principle.html

于 2013-12-13T09:24:10.043 回答
3

ISP很重要。

ISP 的基本思想:不应强迫客户依赖它不使用的方法。

这个原则似乎更符合逻辑。理想情况下,客户端不应实现客户端不使用的方法。

有关代码示例,请参阅下面的 SE 问题:

接口隔离原则——程序到接口

好处:

  1. 灵活性:在没有 ISP 的情况下,您有一个通用 FAT 接口和许多实现它的类。假设您有 1 个接口和 50 个类。如果接口发生变化,则所有 50 个类都必须更改其实现。

    使用 ISP,您可以将通用 FAT 接口划分为细粒度的小接口。如果小粒度接口发生变化,只有实现该接口的类会受到影响。

  2. 可维护性和易用性:由于更改仅限于细粒度接口而不是通用 FACT 接口,因此代码维护更容易。不相关的代码不再是实现类的一部分。

于 2016-10-14T11:45:30.457 回答
2

罗伯特马丁关于这个主题的论文给出了一个很少被提及的解释:

客户端对接口施加的反向力。

如果两个类直接依赖于第三类的两种不同方法,则会增加对前两个类中的任何一个的更改会影响另一个的可能性。

假设我们有三个类:RedGreenBlue

Red两者Green都取决于Blue,但每个都取决于不同的方法。这意味着这Red取决于一种方法,Blue但不使用另一种方法。同样,Green取决于Blue,但仅使用一种方法,而不使用另一种方法。

违反原则是因为每个都依赖于一个类 -Red但至少没有使用它的一个方法GreenBlue

这可能会产生什么问题?

  • 我需要改变Red,我也Blue需要改变以适应Red.
  • 我没有改变具体的方法BlueGreen取决于,但仍然Green依赖Blue,我已经改变了Blue,这仍然会影响Green
  • 因此,我的更改Red可能会产生影响Blue,因为它们导致我更改了一个两者都依赖的类。

这就是“倒退的力量”。我们有时会因为客户的需要而更改课程。如果该课程有不同的客户将其用于不同的事情,我们就有影响他们的风险。

如前所述,接口隔离原则的简单定义是:

不应强迫任何客户依赖它不使用的方法。

在罗伯特·马丁论文的上述观点和上述观点之间,很明显,对 ISP 的许多解释实际上是在谈论其他原则。

  • 具有大量方法的类或接口是不可取的,但不是专门因为 ISP。他们可能违反单一职责。但是 ISP 违规不在大接口或大类中 -如果它们不使用大接口的所有方法,则在依赖于大接口的类中。如果他们使用所有方法,听起来仍然很混乱,但这与 ISP 无关。
  • 实现接口但为某些方法抛出异常的类是不好的,但这也不是 ISP。ISP 是关于依赖于接口的类,而不是实现接口的类。

如果我们用谷歌搜索“接口隔离”,大多数包含代码示例的顶级结果都展示了没有完全实现接口的类,这不是 ISP 的重点。有些人甚至错误地重申了这一原则:

接口隔离原则指出不应强迫客户端实现他们不使用的接口

...但这不是原则。定义文件提到了违反 ISP 的副作用,但指出它们是 Liskov Substitution 违规。

此外,每次将新接口添加到基类时,都必须在派生类中实现(或允许默认)该接口。实际上,相关的做法是将这些接口作为 nil 虚函数而不是纯虚函数添加到基类中;特别是这样派生类就不必承担实现它们的需要。正如我们在本专栏的第二篇文章中了解到的那样,这种做法违反了 Liskov 替换原则(LSP),导致了维护和可重用性问题。

更重要的是,说客户端不应该实现它不使用的方法甚至没有意义。接口的客户端不实现他们使用或不使用的方法——他们使用它的方法。的客户端List<E>实现的方法和属性List<E>。它调用的方法和属性List<E>

我并不是要夸张地引用这篇论文,就好像它是神圣的令状或什么的。但是如果我们要使用文章中描述的原理的名称(文章本身的名称),那么我们还应该考虑该文章中包含的实际定义和解释。

于 2019-05-31T15:38:29.627 回答