根据接口隔离原则
不应强迫客户端实现接口的不需要的方法
...因此我们应该定义接口以进行逻辑分离。
但是default
Java 8 中引入的方法提供了在 Java 接口中实现方法的灵活性。似乎 Java 8 提供了增强接口的可行性,使其具有一些与其核心逻辑无关的方法,但具有一些默认或空实现。
它不违反ISP吗?
根据接口隔离原则
不应强迫客户端实现接口的不需要的方法
...因此我们应该定义接口以进行逻辑分离。
但是default
Java 8 中引入的方法提供了在 Java 接口中实现方法的灵活性。似乎 Java 8 提供了增强接口的可行性,使其具有一些与其核心逻辑无关的方法,但具有一些默认或空实现。
它不违反ISP吗?
好问题。毫无疑问,它违反了接口隔离原则,我个人不喜欢默认实现的概念,因为它破坏了接口设计的美感,也有点影响精确的多态性。如果有人不了解 ISP 的概念,那么他们将开始设计胖接口,最终会像所有东西都打包在一个接口中一样。在代码设计过程中,人们也不会进行逻辑思考。
这最终会产生代码异味,我相信那些不了解这些概念的人会开始编写糟糕的代码。我相信默认实现是一个不需要的功能,因为它会使人们编写臭代码。
如果您打算这样做,将违反 ISP。您可以隔离接口以仅履行单一职责。特定职责的方法组很可能遵循 80-20 规则。您可以为 80% 部分中的 40-50% 的方法提供默认实现。这 40-50% 的部分将是很少使用的部分,因此默认值是可以的。如果接口履行单一职责,它们很少会太大,而且大多数情况下会在 ISP 中。
不。
事实上,默认方法是提供额外有用功能同时避免违反 ISP 的好方法。
我在这里的较长答案的摘录:
default
良好使用方法的标准库中有示例。一个是java.util.function.Function
它的andThen(...)
和compose(...)
方法。...
这些默认方法不违反 ISP,因为实现的类Function
不需要调用或覆盖它们。可能有许多用例,其中 Function 的具体实例永远不会andThen(...)
调用它们的方法,但这很好 - 只要您不妨碍所有这些用例,就不会通过提供有用但非必要的功能来破坏 ISP通过强迫他们做某事。在 Function 的情况下,将这些方法作为抽象而不是默认提供会违反 ISP,因为所有实现类都必须添加自己的实现,即使它们知道它不太可能被调用。
OP中的报价不太准确。ISP的实际声明是,
不应强迫客户依赖他们不使用的接口。
客户端是接口的消费者,即抽象方法的调用者。客户端不是接口的实现者。如果我们遵循依赖倒置原则,客户端甚至不应该知道接口的具体实现。
ISP 背后的原因不是为了让开发人员免于实现额外的抽象方法。这是为了将那些方法的调用者从不必要的传递依赖中拯救出来。额外的接口方法可能会引入额外的依赖项(通过声明或实现)。不使用这些方法的客户端仍然会获取这些依赖项,并通过这些客户端对接口及其共享实现的更改与使用这些方法的客户端耦合。
将此原则应用于default
Java 8 中的方法,这种方法肯定有可能通过添加并非所有客户端都需要的依赖项来违反 ISP。另一方面,一种default
方法也有可能(并且更可取)不添加任何依赖项并且永远不会以任何破坏客户端的方式进行更改。
总之,default
方法只是另一种工具。它们可能被用来帮助或伤害你的代码。