头图

🔥 解锁Node.js中的五大设计模式

前言

大家好,我是倔强青铜三。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。


五种必知的Node.js设计模式

🟢 什么是设计模式?

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

Node.js由于其灵活性,并不强制您遵循某些模式,而是给予您选择所需模式的自由。这就是为什么我认为它今天被广泛使用的原因(顺便提一下,还得益于JavaScript :D)。

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

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

单例模式

这种模式涉及只能有一个实例的类,并提供全局访问。在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'
  }
}

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

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

console.log(redisOne === redisTwo); // 它会返回 `true`

redisOne.connect();

console.log(redisOne.connection) // 'Redis connected'
console.log(redisTwo.connection) // 'Redis connected'

这种方法确保了只有一个到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');
    }
  }
}

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

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

这种方法允许工厂的使用者使用工厂代码而不是直接使用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}`);
  }
}

然后你可以这样使用它:

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

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

装饰器模式

这种模式对于在不影响初始/原始实例的情况下用新功能扩展现有功能非常有用。它在Nest.js框架中得到了广泛使用,这要归功于对TypeScript的完全支持,但在常规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; 
  }
}

然后可以这样使用它:

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

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

依赖注入模式

在这种模式中,类或模块从外部源接收依赖项,而不是在内部注册它们。这种方法允许从系统中提取某些可重用元素,以便更容易地进行测试和维护。它在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;
  }
}

然后,你可以这样使用它:

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

const userService = new UserService(databaseService, loggerService);

userService.getUser(1);

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

✅ 总结

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

保重,下次见!

祝您编码愉快 🖥️


倔强青铜三
21 声望0 粉丝