本文档概述了 SOLID 原则及其在 JavaScript 中的实现。SOLID 是五个设计原则的首字母缩写,它们有助于开发人员编写更易于维护、更灵活、更具可扩展性的代码。本页涵盖了每个原则的定义、在 JavaScript 中的应用以及实际示例。有关类的通用信息,请参阅 类,有关组合与继承的详细信息,请参阅 组合与继承。
SOLID 原则是 Robert C. Martin 提出的五项设计原则,旨在创建更易于维护和扩展的软件。这些原则与语言无关,但可以有效地应用于 JavaScript 开发。正确实施 SOLID 原则有助于降低代码复杂性,提高可读性,并使代码库更易于扩展。
五项原则是
单一职责原则指出,一个类或模块应该只有一个引起它变化的原因。换句话说,一个类应该只有一个职责或任务。
在下面的示例中,UserSettings 类同时处理用户设置和身份验证,违反了 SRP。
SRP 违规: UserSettings 类同时处理身份验证和设置更改。
符合 SRP: 职责被分离到两个类中
UserAuth:处理身份验证UserSettings:处理设置操作,并使用 UserAuth 进行验证开闭原则指出,软件实体(类、模块、函数)应该对扩展开放,但对修改关闭。这意味着您应该能够在不更改现有代码的情况下添加新功能。
下图展示了演示开闭原则的 HTTP 请求处理
OCP 违规: HttpRequester 类会检查适配器类型,并为每种类型提供不同的实现,添加新适配器时需要修改。
符合 OCP
Adapter 定义了通用接口AjaxAdapter、NodeAdapter)提供特定实现HttpRequester 可以与任何实现该接口的适配器一起使用里氏替换原则指出,超类对象的实例应该可以用子类对象的实例替换,而不影响程序的正确性。子类型必须可以替换其基类型。
该原则通常以经典的矩形-正方形问题来说明
LSP 违规: Square 类继承自 Rectangle,但改变了 setWidth 和 setHeight 的行为,当在需要 Rectangle 的地方使用 Square 时会导致意外结果。
符合 LSP: 不再继承,而是 Rectangle 和 Square 都是通用 Shape 接口的独立实现,每个实现都有其适当的计算。
接口隔离原则指出,客户端不应被迫依赖它们不使用的接口。创建多个专门的接口比一个通用接口要好。
下图展示了 DOM 遍历实现中的 ISP
ISP 违规: DOMTraverser 类要求客户端提供一个 animationModule,即使它们不需要动画功能。
符合 ISP: 改进的 DOMTraverser 实现通过选项对象使模块成为可选的,允许客户端仅包含它们需要的接口。
依赖倒置原则指出,高层模块不应依赖于低层模块。两者都应依赖于抽象。此外,抽象不应依赖于细节;细节应依赖于抽象。
库存跟踪系统演示了 DIP
DIP 违规: InventoryTracker 直接实例化一个特定的 InventoryRequester 实现,造成了紧耦合。
符合 DIP
InventoryTracker 接受任何实现所需接口的请求者在 JavaScript 开发中应用 SOLID 原则有许多好处
| 原则 | 关键优势 | 对代码的影响 |
|---|---|---|
| 单一职责 | 提高可维护性 | 具有专注职责的类/模块 |
| 开闭原则 | 扩展时风险降低 | 无需修改现有代码即可扩展 |
| 里氏替换原则 | 可预测的行为 | 子类型保持预期行为 |
| 接口隔离原则 | 专注的客户端接口 | 不依赖未使用的函数 |
| 依赖倒置 | 降低耦合度 | 高层策略独立于低层细节 |
虽然 SOLID 原则提供了宝贵的指导,但它们应在 JavaScript 中务实地应用
有关 SOLID 相关整洁代码原则的进一步探讨