Node.js 中需要了解的五种设计模式

2025-05-25

Node.js 中需要了解的五种设计模式

嘿!

最近,我查阅了多个知识资源,以进一步了解 Node.js 中流行的设计和架构模式。我主要针对的是服务器端(后端),但随着查阅的深入,我发现它们与浏览器端(前端)框架有很多相似之处。其中一些甚至直接被用在了框架中,这让我更开心,因为我之前在不知不觉中就已经在使用它们了 😉

您可以使用很多(真的很多)设计模式,因此在本文中,我决定选择其中 5 种并更详细地解释它们。

享受!

🟢 什么是设计模式?

设计模式是经过实践检验的解决方案,能够解决我们开发人员每天遇到的问题。这些模式有助于推广最佳实践,并在设计和开发软件架构时,实现一种结构化的方法来解决日常问题。软件工程师可以使用这些模式开发可维护、安全且稳定的系统。

Node.js 灵活性极高,它不会强迫你遵循某些模式,而是让你自由选择适合你任务的模式。在我看来,这正是它如今如此广泛使用的原因(顺便说一句,这也要感谢 JavaScript :D)。

✅ Node.js 中的五种流行设计模式

下面,您将看到我喜欢的 5 种精选设计模式的列表。

单例模式

这种模式的核心是类只能拥有一个实例,并提供全局访问。在 Node.js 中,模块可以缓存并在应用程序中共享,这有助于提高资源利用效率。这种单例模式的一个常见示例是用于连接某些第三方服务(例如数据库、缓存服务、电子邮件提供商等)的模块,该模块在 Nest.js 框架中被广泛使用。让我们来看以下示例:

class Redis {
  constructor() {
    this.connection = null;
  }

  static getInstance() {
    if (!Redis.instance) {
      Redis.instance = new Redis(options);
    }

    return Redis.instance;
  }

  connect() {
    this.connection = 'Redis connected'
  }
}
Enter fullscreen mode Exit fullscreen mode

然后我们可以像下面这样使用它:

const redisOne = Redis.getInstance();
const redisTwo = Redis.getInstance();

console.log(redisOne === redisTwo); // it will result to `true`

redisOne.connect();

console.log(redisOne.connection) // 'Redis connected'
console.log(redisTwo.connection) // 'Redis connected'
Enter fullscreen mode Exit fullscreen mode

这种方法确保只有一个与 Redis 的连接,并防止重复连接。

工厂

使用此模式,您可以创建新对象而无需指定要创建的对象类。得益于此,我们抽象了对象的创建,这有助于提高代码的可读性和可重用性:

class Character {
  constructor(type, health) {
    this.type = type;
    this.health = health;
  }
}

class CharacterFactory {
  createCharacter(name) {
    switch(name) {
      case 'mage': 
        return new Character('Powerful Mage', 8);
      case 'warrior':
        return new Character('Courageous Warrior', 10);
      case 'rogue':
        return new Character('Sneaky Rogue', 9)
      default:
        return new Error('Unknown character');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

然后我们可以像下面这样使用它:

const characterFactory = new CharacterFactory();

const mage = characterFactory.createCharacter('mage');
const warrior = characterFactory.createCharacter('warrior');

console.log(mage.type) // Powerful Mage
console.log(warrior.type) // Courageous Warrior
Enter fullscreen mode Exit fullscreen mode

这种方法允许该工厂的消费者使用工厂代码,而不是直接使用 Character 类构造函数。

观察者

这种模式的工作方式是,你将拥有一个实体,该实体管理依赖元素列表(称为观察者),并在状态发生变化时通知它们。这种模式在 Vue.js 框架中被广泛使用,实现方式如下:

class Topic {
  constructor() {
    this.observers = []; 
  }

  subscribe(observer) {
    this.observers.push(observer);
  }

  unsubscribe(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }

  notify(data) {
    this.observers.forEach(o => o.update(data));
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }

  update(data) {
    console.log(`${this.name} received ${data}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

您可以像下面这样使用它:

const topic = new Topic();

const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');

topic.subscribe(observer1);
topic.subscribe(observer2);

topic.notify('Hello World');
// Observer 1 received Hello World 
// Observer 2 received Hello World

topic.unsubscribe(observer2);

topic.notify('Hello Again');
// Observer 1 received Hello Again
Enter fullscreen mode Exit fullscreen mode

对于事件处理和异步工作流来说,这是一种非常有用的模式,它允许更新多个对象,而无需将发布者与订阅者耦合。

装饰器

这种模式对于在不影响初始/原始实例的情况下使用新功能扩展现有功能非常有用。由于 TypeScript 的全面支持,它在 Nest.js 框架中被广泛使用,但在常规 Node.js 中,它可以用于以下情况:

class Character {
  constructor() {
    this.endurance = 10;
  }

  getEndurance() {
    return this.endurance;
  }
}

class CharacterActions {
  constructor(character) {
    this.character = character;
  }

  attack() {
    this.character.endurance -= 2;
  }

  rest() {
    this.character.endurance += 1; 
  }
}
Enter fullscreen mode Exit fullscreen mode

然后就可以像下面这样使用了:

const character = new Character();

console.log(character.getEndurance()); // 10

const characterWithActions = new CharacterActions(character);

characterWithActions.attack(); // - 2
characterWithActions.rest(); // + 1

console.log(characterWithActions.character.getEndurance()); // 9
Enter fullscreen mode Exit fullscreen mode

通过使用这种模式,我们可以轻松扩展现有的类,而不会影响其核心功能。

依赖注入

在此模式中,类或模块从外部源接收依赖项,而不是在内部注册它们。这种方法允许从系统中提取某些可重用元素,以便于测试和维护。它在 Nest.js 框架中被广泛使用。它可以像下面这样实现:

class UserService {
  constructor(databaseService, loggerService) {
    this.db = databaseService;
    this.logger = loggerService;
  }

  async getUser(userId) {
    const user = await this.db.findUserById(userId);
    this.logger.log(`Fetched user ${user.name}`);
    return user;
  }
}
Enter fullscreen mode Exit fullscreen mode

然后,您可以像下面这样使用它:

const databaseService = new Database();
const loggerService = new Logger();

const userService = new UserService(databaseService, loggerService);

userService.getUser(1);
Enter fullscreen mode Exit fullscreen mode

这种方法允许您将系统元素提取为独立实体,以便在需要时注入。

📖 了解更多

如果您想了解有关 Vue、Nuxt、JavaScript 或其他有用技术的更多信息,请点击此链接或点击下图查看 VueSchool:

Vue 学校链接

它涵盖了构建现代 Vue 或 Nuxt 应用程序时最重要的概念,可帮助您完成日常工作或副项目😉

✅ 总结

做得好!您刚刚了解了 Node.js 中某些设计模式的工作原理以及如何实现它们。

保重,下次再见!

和往常一样快乐编码🖥️

文章来源:https://dev.to/jacobandrewsky/ Five-design-patterns-to-know-in-nodejs-265h
PREV
10 个 Git 技巧,助您节省时间和精力 以交互方式暂存文件的各个部分以进行提交 重新排列(或完全重写)分支的历史记录
NEXT
使用 React、Strapi、Nginx、MongoDB 和 DigitalOcean 创建全栈 Web 应用程序步骤:步骤 1 - 创建和配置 DigitalOcean Droplet:步骤 2 - 设置域名步骤 3 - 使用 Let's Encrypt 设置 Nginx 和 SSL步骤 4 - 创建 MongoDB Atlas 集群步骤 5 - 创建和部署 Create-React-App 站点步骤 6 - 创建和部署 Create-Strapi-App API 结论