菜单

接口隔离原则

相关源文件

目的与范围

本文档解释了接口隔离原则(ISP),它是 SOLID 设计原则中的第四个原则,以及如何在 JavaScript 中应用它。虽然 JavaScript 缺乏 Java 或 C# 等语言中的正式接口,但该原则通过 JavaScript 的隐式契约和鸭子类型仍然适用。本页面涵盖了如何识别 ISP 违规、在 JavaScript 中实现接口隔离以及重构代码以更好地遵循该原则。

有关其他 SOLID 原则的信息,请参阅 SOLID 原则单一职责原则开闭原则里氏替换原则依赖倒置原则

什么是接口隔离?

接口隔离原则规定“客户端不应被迫依赖它们不使用的接口。” 本质上,不应强制客户端实现它不需要的方法,或依赖它不使用的方法。

在 JavaScript 中,接口通过对象之间交互的方式是隐式的。当一个对象期望另一个对象具有某些属性或方法时,它们之间就形成了隐式接口。

来源: README.md1651-1727

JavaScript 中的接口隔离

与静态类型语言不同,JavaScript 没有正式的接口声明。然而,ISP 仍然通过以下方式适用:

  1. 鸭子类型 - 对象以其属性和行为为特征,而不是以其显式类型为特征。
  2. 方法期望 - 当函数期望其参数具有某些方法时
  3. 配置对象 - 当函数需要具有特定属性的对象时

“肥接口”的问题

肥接口迫使客户端了解并可能实现它们不需要的方法。这会产生几个问题:

  1. 不必要的耦合 - 对未使用的修改仍然会影响客户端
  2. 实现负担 - 客户端必须实现它们不需要的方法
  3. 认知负荷 - 开发人员必须理解整个接口
  4. 降低内聚性 - 肥接口通常内聚性较低

来源: README.md1651-1725

在 JavaScript 中实现 ISP

示例:DOMTraverser 类

README 展示了一个清晰的 ISP 违规示例以及如何使用 DOMTraverser 类来修复它。

糟糕的模式(违反 ISP):在此示例中,即使不需要 animationModule,客户端也被迫提供它。

来源: README.md1670-1691

良好的模式(遵循 ISP):改进后的版本通过将可选功能放入单独的 options 对象中,使可选功能真正可选。

来源: README.md1693-1725

实施技术

技术描述优点
可选参数使参数可选并提供默认值客户端只提供他们需要的东西
配置对象将相关参数分组到可选对象中减少参数数量,使需求更清晰
功能检测在使用功能前检查它们允许优雅降级
组合从简单对象构建复杂对象每个组件都有一个集中的接口

来源: README.md1693-1725

实现模式

  1. 方法检查 在尝试使用方法之前检查它们是否存在

  2. 可选链 使用可选链进行更简洁的方法检查

  3. 默认空对象 提供默认空对象以避免需要检查存在性

来源: README.md1693-1725

ISP 的实际应用

配置对象

README 中的 DOMTraverser 示例展示了如何使用嵌套的配置对象来使接口需求更加灵活。

这种模式在需要处理大量配置选项但又希望其中大部分是可选的 JavaScript 库中很常见。

来源: README.md1696-1724

模块系统

现代 JavaScript 模块系统通过允许选择性导入来遵循 ISP。

这种模式允许现代打包工具进行“树抖动”,并通过确保消费者只依赖他们实际使用的内容来遵循 ISP。

与其他 SOLID 原则的联系

接口隔离与其他 SOLID 原则紧密合作。

来源: README.md1380-1828

最佳实践

  1. 分解大型接口为小型接口

    • 创建服务于特定客户端需求的集中接口
    • 根据接口的目的命名接口,而不是实现
  2. 使用可选属性和合理的默认值

    • 使非必要的属性可选
    • 提供适用于大多数用例的默认值
  3. 实现功能检测

    • 在使用功能/方法之前检查它们是否存在
    • 当可选功能不可用时,优雅地回退
  4. 组合优于继承

    • 从更小、更集中的组件组合对象
    • 每个组件都可以实现自己的接口
  5. 优先考虑消费者的需求

    • 根据接口的用途来设计它们
    • 不同的消费者可能需要不同功能的子集

来源: README.md1693-1725

重构违规

当遇到 ISP 违规时,应用这些重构策略:

违规模式重构策略
必需但未使用的参数使参数可选并提供默认值
大型配置对象分解为更小、更集中的对象
具有许多方法的类分解为更小、可组合的类
必需的回调函数可能未使用使回调函数可选或使用事件发射器

来源: README.md1670-1725

结论

虽然 JavaScript 缺乏正式的接口,但接口隔离原则仍然是设计灵活、可维护代码的宝贵指南。通过确保客户端只依赖他们实际使用的功能,您可以创建更健壮、松耦合的系统,这些系统更容易测试、重构和维护。

在 JavaScript 中遵循 ISP 时

  • 使非必要的属性和方法可选
  • 将相关选项分组到专用对象中
  • 使用组合创建实现多个接口的对象
  • 根据消费者的需求进行设计

这些实践可以带来更模块化的代码,减少依赖性并增加灵活性。