接口隔离原则 (ISP) 指出,许多客户端特定接口比一个通用接口更好。为什么这很重要?

有帮助吗?

解决方案

ISP 声明:

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

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

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

  • 高的 凝聚 - 更好的可理解性、稳健性
  • 低的 耦合 - 更好的可维护性,高抗变化性

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

其他提示

界面隔离是 SOLID 原则上的“I”,在深入研究第一个之前,让我们先解释一下后者的含义。

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

我为什么要关心 SOLID 编程?

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

接口隔离原则。

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

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

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

enter image description here

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

enter image description here

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

public interface Reportable {

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


}

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

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

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

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

这一原则主要有两个目的

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

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

设计人员必须向 ISP 询问几个问题

  • 通过 ISP 可以实现什么目标
  • 如何分析现有代码是否存在任何 ISP 违规行为

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

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

互联网服务供应商 很重要。

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

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

请参阅以下 SE 问题的代码示例:

接口隔离原则 - 对接口进行编程

优点:

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

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

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

当只有一种特定于客户或一种特定于行为的变化时,避免回归工作。如果您将所有行为方法都组合在一个大接口中,那么只需考虑一下您将如何最终测试所有您所引用的代码片段,即使只发生了很小的更改也是如此。

更详细的解释可以参考 接口隔离原理文章

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

客户端在接口上施加的向后力。

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

假设我们有三个类: Red, Green, , 和 Blue.

RedGreen 两者都依赖 Blue, ,但每个都取决于不同的方法。这意味着 Red 取决于一种方法 Blue 但不使用其他方法。同样地, Green 依赖于取决于 Blue, ,但只使用一种方法,而不使用另一种。

违反原则的情况是 RedGreen 因为每个都取决于一个类 - Blue - 但 至少使用其中一种方法。

这可能会产生什么问题?

  • 我需要改变 Red, ,我也改变 Blue 以满足 Red.
  • 我没有改变里面的具体方法 BlueGreen 取决于,但尽管如此, Green 依赖于取决于 Blue 我已经改变了 Blue, ,这仍然可能影响 Green.
  • 因此,我的更改为 Red 有潜力影响 Blue 因为他们引导我改变了两个都依赖的类。

那就是“向后部队”。由于客户的需求,我们有时会更改课程。如果该类有不同的客户使用它来做不同的事情,我们就有影响他们的风险。

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

任何客户端都不应被迫依赖于它不使用的方法。

结合这一点和 Robert Martin 论文中的上述观点,很明显,许多对 ISP 的解释实际上是在谈论其他原则。

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

如果我们谷歌“接口隔离”,大多数包含代码示例的顶级结果都展示了以下类: 不完全执行 接口,这不是 ISP 的重点。有些人甚至重申了这个原则:

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

...但那是 不是 原则。定义文件提到这些担忧是违反 ISP 的副作用,但指出它们是违反里氏替换的。

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

更重要的是,说客户端不应该实现它不使用的方法甚至没有意义。这 客户 接口的方法不实现它的方法。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top