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'
}
}
然后我们可以像下面这样使用它:
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'
这种方法确保只有一个与 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
对于事件处理和异步工作流来说,这是一种非常有用的模式,它允许更新多个对象,而无需将发布者与订阅者耦合。
装饰器
这种模式对于在不影响初始/原始实例的情况下使用新功能扩展现有功能非常有用。由于 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;
}
}
然后就可以像下面这样使用了:
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);
这种方法允许您将系统元素提取为独立实体,以便在需要时注入。
📖 了解更多
如果您想了解有关 Vue、Nuxt、JavaScript 或其他有用技术的更多信息,请点击此链接或点击下图查看 VueSchool:
它涵盖了构建现代 Vue 或 Nuxt 应用程序时最重要的概念,可帮助您完成日常工作或副项目😉
✅ 总结
做得好!您刚刚了解了 Node.js 中某些设计模式的工作原理以及如何实现它们。
保重,下次再见!
和往常一样快乐编码🖥️
文章来源:https://dev.to/jacobandrewsky/ Five-design-patterns-to-know-in-nodejs-265h