为了账号安全,请及时绑定邮箱和手机立即绑定

五个你需要知道的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 School 链接到 Vue School

它涵盖了构建现代 Vue 或 Nuxt 应用程序所需的重要概念,这些概念可以在您的工作中或个人项目中帮助您 😉

✅ 摘要

做得好!你刚刚学会了在Node.js中如何使用一些设计模式以及如何实现这些模式。

多保重,下次再聊!

祝你一如既往地编码愉快 🖥️

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消