接口隔离原则(ISP)表示许多客户端特定接口优于一个通用接口。为什么这很重要?
答案 0 :(得分:31)
ISP声明:
客户不应该被迫依赖 关于他们不使用的方法。
ISP涉及重要特征 - cohesion和coupling 理想情况下,您的组件必须高度定制。它提高了代码的健壮性和可维护性。
执行ISP会为您提供以下奖励:
如果您想了解有关软件设计原则的更多信息,请获取副本 Agile Software Development, Principles, Patterns, and Practices本书。
答案 1 :(得分:7)
接口隔离是SOLID原则上的“I”,在深入挖掘第一个之前,让我们解释后者的意思。
SOLID可以被视为一组专家提出的最佳实践和建议(意思是之前已经证明),以便为我们设计应用程序提供可靠的基础。这些实践旨在使我们的应用程序更易于维护,扩展,调整和扩展。
我为什么要关心SOLID编程?
首先,你必须意识到你不会永远在你身边。如果我们使用标准和众所周知的体系结构,我们可以确保我们的代码很容易被我们之后的其他开发人员维护,我相信你不会想要处理修复代码的任务。没有应用任何已知的方法,因为它很难理解。
界面隔离原则。
知道我们知道什么是SOLID原则我们可以更详细地了解接口隔离原理,但接口隔离究竟是什么意思?
“客户不应该被迫实施不必要的方法 他们不会使用“
这意味着有时候我们倾向于使用很多方法创建接口,这在某种程度上可能是好的,但这很容易被滥用,我们最终会得到实现空或无用方法的类,这当然会增加额外的我们的应用程序的代码和负担。 想象一下,你在单个界面中声明了很多方法,如果你喜欢视觉辅助,那么实现一个接口但实际上需要它的几个方法的类看起来像这样:
另一方面,如果你正确应用界面隔离并将界面拆分为较小的子集,我可以确保实现那些只需要的界面:
请参阅!好多了!执行此原则将允许您具有低耦合,这有助于更好的可维护性和对变化的高抵抗力。因此,您可以真正利用接口的使用并在实际应用时实现这些方法。 现在让我们回顾一个不那么抽象的例子,比如说你声明了一个名为Reportable
的接口public interface Reportable {
void printPDF();
void printWord();
void printExcel();
void printPPT();
void printHTML();
}
你有一个只能以Excel格式导出一些数据的客户端,你可以实现这个界面,但是你只需要实现excel方法吗?答案是否定的,即使您不打算使用它们,也必须为所有方法编写实现代码,这会导致大量垃圾代码,从而使代码难以维护..
请记住保持简单,不要重复自己,你会发现你已经在不知情的情况下使用这个原则。
答案 2 :(得分:5)
它简化了任何一个客户端将使用的接口,并删除了他们可能在他们不需要的接口部分上开发的依赖关系。
答案 3 :(得分:3)
一个原因是,每个接口都有少量方法,可以更容易地实现每个接口并正确实现它们。大型界面可能难以驾驭。此外,在场景中使用聚焦接口使得代码更具可维护性,因为您可以看到正在使用对象的哪个方面(例如,IComparable接口让您知道该对象仅用于在给定方案中进行比较)。
答案 4 :(得分:3)
这个原则主要用于双重目的
使代码更具可读性和可管理性。
促进课程的单一责任(高凝聚力)。当然为什么班级应该有一种没有行为影响的方法?为什么不删除它。这就是ISP的意思
设计师必须向ISP提出问题并提出一些问题
为了进一步讨论,我还必须补充一点,这个原则并不是最严格意义上的“原则”,因为在某些情况下,将ISP应用于设计而不是提高可读性可能会使对象结构难以理解并且不必要的代码混乱。 您可以在java.awt.event包
中观察到这一点点击我的博客:http://design-principle-pattern.blogspot.in/2013/12/interface-segregation-principle.html
答案 5 :(得分:1)
ISP很重要。
ISP的基本思想:客户不应该被迫依赖它不使用的方法。
这个原则似乎更符合逻辑。理想情况下,客户端不应实现客户端不使用的方法。
有关代码示例,请参阅下面的SE问题:
Interface Segregation Principle- Program to an interface
优点:
灵活性:在没有ISP的情况下,您有一个通用FAT接口和许多实现它的类。假设您有1个接口和50个类。如果界面发生变化,则所有50个类都必须更改其实现。
使用ISP,您可以将通用FAT接口划分为精细的小型接口。如果小粒度接口发生更改,则只会影响实现该接口的类。
可维护性和易用性:由于更改仅限于细粒度界面而非通用FACT界面,因此代码维护更容易。不相关的代码不再是实现类的一部分。
答案 6 :(得分:0)
为了避免回归工作,只需要一个特定于客户端或一个特定于行为的更改。如果您将所有行为方法都集中在一个BIG界面中,那么只需考虑如何最终测试所有代码片段,即使只发生了很小的变化,即使只是发生了很小的变化。
有关更详细的说明,请参阅Interface segregation principle article
答案 7 :(得分:0)
Robert Martin's paper关于这个问题的解释很少被提及:
客户端在接口上施加的反向力。
如果两个类直接依赖于第三类的两种不同方法,则会增加对前两个类之一进行更改会影响另一个类的可能性。
假设我们有三个类:Red
,Green
和Blue
。
Red
和Green
都依赖于Blue
,但是都依赖于不同的方法。这意味着Red
依赖于Blue
的一种方法,而不使用另一种方法。同样,Green
依赖于Blue
,但仅使用一种方法,而不使用另一种方法。
在Red
和Green
中违反了该原则,因为每个都依赖于一个类-Blue
-但是不至少使用以下一个它的方法。
这可能会导致什么问题?
Red
,并且也要更改Blue
以适应Red
的需求。 Blue
所依赖的Green
中的特定方法,但是Green
依赖于Blue
,并且我已经更改了Blue
,但仍可能影响Green
。 Red
所做的更改有可能影响Blue
,因为它们使我改变了两者都依赖的课程。那是“向后力量”。我们有时会根据客户的需求更改班级。如果该班级有不同的客户将其用于不同的事物,则我们有可能影响他们。
如上所述,接口隔离原理的简单定义是:
不应强迫任何客户端依赖于不使用的方法。
在这与罗伯特·马丁(Robert Martin)论文的上述观点之间,很明显,对ISP的许多解释实际上是在谈论其他原理。
如果我们使用Google“接口隔离”,则大多数包含代码示例的顶级结果都证明了不能完全实现接口的类,而这并不是ISP的重点。有些人甚至重申了这一原则:
接口隔离原理规定不应强迫客户端实现其不使用的接口
...但是那不是 原理。定义文件将此类担忧视为违反ISP的副作用,但指出它们是违反Liskov换人条款的。
此外,每次将新接口添加到基类时,该接口必须是 在派生类中实现(或允许默认)。实际上,一种相关的实践是将这些接口作为nil虚拟函数而不是纯虚拟函数添加到基类。特别是,这样派生类就不必承担实现它们的负担。正如我们在本专栏的第二篇文章中了解到的那样,这种做法违反了Liskov替代原则(LSP),从而导致维护和可重用性问题。
此外,说一个客户端不应该实现它不使用的方法甚至没有道理。接口的 clients 不实现其方法。
我的意思并不是要把报纸当作是圣旨或其他东西。但是,如果我们要使用文章中描述的原理的名称(文章本身的名称),那么我们还应该考虑该文章中包含的实际定义和解释。