五个你需要知道的Node.js设计模式
嘿!
最近我翻阅了不少相关资料,以便更多地了解Node.js中流行的“设计模式和架构模式”。我的目标主要集中在服务器端(后端),但在查阅过程中,我发现了很多相似之处,这些模式与浏览器(前端)框架中的模式有很多相似之处。其中一些模式甚至直接被框架所使用,这让我更加高兴,因为我已经在不知不觉中使用了它们 😊
因为你可以使用的设计模式数不胜数,所以在本文里,我将详细解释其中的10种设计模式。
嗨,享受吧!
🟢 什么是设计模式呢?设计模式是经过验证和实战检验的解决方案,用于解决我们作为开发人员每天遇到的问题。这些模式有助于推广最佳实践方法,并在设计和开发软件架构时采用结构化的方法解决问题。通过采用这些模式,软件工程师可以开发出既可维护又安全稳定的系统。
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; // 获取Redis实例的方法
}
connect() {
this.connection = '已连接到Redis'; // 连接到Redis
}
}
全屏显示,退出全屏
然后我们就可以这样用它:
如果后续提供具体的代码段,可以添加一句简短的说明,比如“以下是示例代码:”,但目前不需要添加。
const medicine = Redis.getInstance(); // 医药对象初始化
const redisTwo = Redis.getInstance();
console.log(redisOne === redisTwo); // 它将结果为 `true`
redisOne.connect(); // 连接 Redis
console.log(redisOne.connection); // 'Redis 连接成功'
console.log(redisTwo.connection); // 'Redis 连接成功'
进入全屏,退出全屏
这种方法确保只有一个 Redis 连接,并避免重复建立连接。
工厂
通过这种方式,您可以创建新对象而无需指定要创建的具体对象类型。因此,我们将对象创建过程抽象化,这有助于提升代码的可读性和重用性:
class Character {
constructor(name, health) {
this.name = name;
this.health = health;
}
}
class CharacterFactory {
createCharacter(name) {
switch(name) {
case 'mage':
return new Character('强力法师', 8);
case 'warrior':
return new Character('英勇战士', 10);
case 'rogue':
return new Character('机智盗贼', 9)
default:
return new Error('未知角色类型');
}
}
}
进入全屏(按esc退出)
我们可以这样用它:
# 原始代码保持不变
(注:根据上下文决定是否保留代码部分)
(去掉不必要的代码部分后)
最终翻译:
我们可以这样用它:
const characterFactory = new CharacterFactory();
const mage = characterFactory.createCharacter('mage');
const warrior = characterFactory.createCharacter('warrior');
console.log(mage.name) // 一个强大的魔导
console.log(warrior.name) // 一个勇敢的斗士
进入全屏,退出全屏
这种方法让使用该工厂的人可以使用工厂提供的代码,而不用直接调用Character类的构造方法。
观察者
这种模式的运作方式是你会有一个实体来管理这些依赖元素(也就是观察者),并在状态改变时通知这些观察者。这种模式在 Vue.js 框架中被广泛应用,并可以这样来实现:
class Topic {
constructor() {
this.observers = [];
}
订阅(observer) {
this.observers.push(observer);
}
取消订阅(observer) {
this.observers = this.observers.filter(o => o !== observer);
}
通知(data) {
this.observers.forEach(o => o.更新(data));
}
}
class Observer {
constructor(name) {
this.name = name;
}
更新(data) {
console.log(`${this.name} 接收到了 ${data}`);
}
}
切换到全屏 退出全屏
你可以像下面这样使用它:
(Any code segments from the original text would remain here, untranslated.)
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 收到了 "Hello World",Observer 2 也收到了 "Hello World".
topic.unsubscribe(observer2);
topic.notify('Hello Again');
// 于是,Observer 1 收到了 "Hello Again".
进入全屏,退出全屏
这确实是一个非常有用的模式,在事件处理和异步工作流中,它允许在不耦合发布者和订阅者的情况下更新多个对象。
装饰模式
这种模式非常有用,可以在不影响初始实例的情况下增强现有功能。因此在 Nest.js 框架中,由于 TypeScript 的全面支持,它被广泛使用,但在普通的 Node.js 中,也可以用以下方式来使用。
class 角色 {
constructor() {
this.耐力 = 10;
}
getEndurance() {
// 获取耐力值
return this.耐力;
}
}
class 角色行动 {
constructor(character) {
this.角色 = character;
}
攻击() {
// 攻击时减少耐力
this.角色.耐力 -= 2;
}
休息() {
// 休息时增加耐力
this.角色.耐力 += 1;
}
}
切换到全屏,退出全屏
然后可以像下面这样使用:
const character = new Character();
// 创建一个新的角色对象
console.log(character.getEndurance()); // 10
// 输出角色的耐力值为10
const characterWithActions = new CharacterActions(character);
// 创建一个新的CharacterActions对象,绑定到character角色
characterWithActions.attack(); // - 2
// 攻击,减少耐力2点
characterWithActions.rest(); // + 1
// 休息,增加耐力1点
console.log(characterWithActions.character.getEndurance()); // 9
// 输出角色的耐力值为9
切换到全屏 / 退出全屏
利用这种模式,我们可以轻松扩展已有的类功能而不影响它们的核心功能。
依赖注入
在这个模式中,类或模块从外部获取依赖项,而不是在内部注册它们。这种方法允许将系统中的某些可重用元素提取出来,从而更容易测试和维护。它在 Nest.js 框架中被广泛使用。可以这样实现:
class 用户服务 {
constructor(数据库服务, 日志服务) {
this.db = 数据库服务;
this.logger = 日志服务;
}
async 获取用户(userId) {
const user = await this.db.findById(userId);
this.logger.log(`找到了用户 ${user.name}`);
return user;
}
}
切换到全屏模式,退出全屏
接下来,你可以如下所示使用它:
代码示例如下:
[此处可以保留原文的代码示例,不翻译]
const databaseService = new Database();
const loggerService = new Logger();
const userService = new UserService(databaseService, loggerService);
userService(1);
切换到全屏,退出全屏
这种方法允许你将系统的元素拆分,变成可以在需要时插入的独立实体。
韩国人更常见的是表达为“了解更多”如果您想了解更多关于 Vue、Nuxt、JavaScript 或其他有用的技术,可以点击这个 链接 或者点击下方的图片:
它涵盖了构建现代 Vue 或 Nuxt 应用程序所需的重要概念,这些概念可以在您的工作中或个人项目中帮助您 😉
✅ 摘要做得好!你刚刚学会了在Node.js中如何使用一些设计模式以及如何实现这些模式。
多保重,下次再聊!
祝你一如既往地编码愉快 🖥️
共同学习,写下你的评论
评论加载中...
作者其他优质文章