JavaScript中的SOLID原则:理论与实践

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

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

开始课程

SOLID 原则在 JavaScript 中的介绍

SOLID 是由 Robert Martin(鲍勃大叔)提出的面向对象编程的五个基本原则的首字母缩写。尽管 JavaScript 最初并不是一种严格类型的 OOP 语言,但现代 JavaScript(ES6+)通过类、模块和 TypeScript 积极运用这些原则来构建可扩展且可维护的应用程序,尤其是在 Node.js 环境中。

在本文中,我们将通过 JavaScript 的实际代码示例逐一解析 SOLID 的五个原则。理解这些原则将帮助您编写干净、灵活且易于应对变更的代码。



1. Single Responsibility Principle (SRP) — 单一职责原则

该原则指出:一个类或模块应该只有一个引起它变化的原因。换句话说,每个模块只负责一个特定的功能。

违反 SRP

考虑一个同时管理用户、发送邮件和记录操作的 UserService 类:

class UserService {  constructor() {    this.users = [];  }

addUser(name) { this.users.push({ name }); console.log('User added'); // 日志记录 this.sendEmail(name); // 发送邮件 }

sendEmail(name) { console.log(`Email sent to ${name}`); }

getUsers() { return this.users; }}

这里,该类承担了三个职责:数据管理、日志记录和通知发送。修改日志逻辑或邮件发送逻辑都会导致 UserService 类发生变化。

遵循 SRP

将职责分离到不同的类中:

class Logger {  log(message) {    console.log(`[LOG]: ${message}`);  }}

class EmailService { send(name) { console.log(`Email sent to ${name}`); }}

class UserService { constructor(logger, emailService) { this.users = []; this.logger = logger; this.emailService = emailService; }

addUser(name) { this.users.push({ name }); this.logger.log(`User ${name} added`); this.emailService.send(name); }

getUsers() { return this.users; }}

现在每个类只负责自己的任务,一个服务中的变更不会影响其他服务。



2. Open-Closed Principle (OCP) — 开闭原则

该原则指出:软件实体应该对扩展开放,对修改关闭。也就是说,我们应该能够添加新功能,而无需修改现有代码。

违反 OCP

假设我们有一个计算图形面积的函数:

function calculateArea(shape) {  if (shape.type === 'circle') {    return Math.PI * shape.radius ** 2;  } else if (shape.type === 'rectangle') {    return shape.width * shape.height;  }  // 添加新图形时必须修改此函数}

遵循 OCP

通过类使用多态性:

class Shape {  area() {    throw new Error('Method "area()" must be implemented');  }}

class Circle extends Shape { constructor(radius) { super(); this.radius = radius; } area() { return Math.PI * this.radius ** 2; }}

class Rectangle extends Shape { constructor(width, height) { super(); this.width = width; this.height = height; } area() { return this.width * this.height; }}

// 添加新图形无需修改现有代码class Triangle extends Shape { constructor(base, height) { super(); this.base = base; this.height = height; } area() { return (this.base * this.height) / 2; }}

function calculateArea

博客

书籍推荐