JavaScript中的SOLID原则:从A到Z的理论与实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JavaScript中的SOLID原则:从A到Z的理论与实践

\n\n

开发高质量的软件不仅需要掌握语言的语法,还需要理解架构原则。SOLID 是面向对象设计的五个基本原则,有助于创建灵活、可维护且可扩展的代码。在本文中,我们将结合实践示例,逐一剖析JavaScript(Node.js)环境下的每个SOLID原则。

\n\n

什么是SOLID?

\n\n

SOLID 这个缩写由罗伯特·C·马丁(Bob大叔)提出,包含以下原则:

\n\n
    \n
  • S — 单一职责原则 (Single Responsibility Principle)
  • \n
  • O — 开闭原则 (Open/Closed Principle)
  • \n
  • L — 里氏替换原则 (Liskov Substitution Principle)
  • \n
  • I — 接口隔离原则 (Interface Segregation Principle)
  • \n
  • D — 依赖倒置原则 (Dependency Inversion Principle)
  • \n
\n\n

这些原则具有通用性,适用于包括JavaScript在内的任何编程语言。下面我们逐一详细讲解。

\n\n

1. 单一职责原则 (SRP)

\n\n

定义:一个类或模块应该只有一个引起变化的原因。换句话说,每个模块只负责一个特定的任务。

\n\n

反面示例:一个 UserService 类同时负责保存用户、发送邮件和生成报告。

\n\n
// ❌ 违反SRP\nclass UserService {\n    saveUser(user) {\n        // 保存到数据库\n        console.log('User saved');\n    }\n\n    sendEmail(user) {\n        // 发送邮件\n        console.log('Email sent to ' + user.email);\n    }\n\n    generateReport(user) {\n        // 生成报告\n        console.log('Report generated for ' + user.name);\n    }\n}
\n\n

正确示例:将职责拆分到不同的类中。

\n\n
// ✅ 遵循SRP\nclass UserRepository {\n    save(user) {\n        console.log('User saved');\n    }\n}\n\nclass EmailService {\n    send(user) {\n        console.log('Email sent to ' + user.email);\n    }\n}\n\nclass ReportGenerator {\n    generate(user) {\n        console.log('Report generated for ' + user.name);\n    }\n}\n\n// 使用\nconst user = { name: '伊万', email: 'ivan@example.com' };\nconst userRepo = new UserRepository();\nconst emailService = new EmailService();\nconst reportGen = new ReportGenerator();\n\nuserRepo.save(user);\nemailService.send(user);\nreportGen.generate(user);
\n\n

现在每个类只有一个职责,一个模块的修改不会影响其他模块。

\n\n

2. 开闭原则 (OCP)

\n\n

定义:软件实体(类、模块、函数)应该对扩展开放,对修改关闭。

\n\n

反面示例:一个计算图形面积的函数使用了条件语句。

\n\n
// ❌ 违反OCP\nfunction calculateArea(shape) {\n    if (shape.type === 'circle') {\n        return Math.PI * shape.radius ** 2;\n    } else if (shape.type === 'rectangle') {\n        return shape.width * shape.height;\n    }\n    // 添加新图形时必须修改函数\n    return 0;\n}
\n\n

正确示例:使用多态和继承。

\n\n
// ✅ 遵循OCP\nclass Shape {\n    area() {\n        throw new Error('area() 方法必须被实现');\n    }\n}\n\nclass Circle extends Shape {\n    constructor(radius) {\n        super();\n        this.radius = radius;\n    }\n\n    area() {\n        return Math.PI * this.radius ** 2;\n    }\n}\n\nclass Rectangle extends Shape {\n    constructor                

博客

书籍推荐