2024 年 8 大 Node.js 设计模式

2025年2月27日 | 阅读 9 分钟

Node.js 是一个流行的 JavaScript 运行时环境,可用于构建复杂的后端系统。由于其众多功能,设计模式的集成可能具有挑战性。借助设计模式,开发人员可以编写更有效、可重用和可测试的代码。一些设计模式已集成到 Node.js 中,而另一些则可与其他编程语言一起使用。开发人员可以使用功能强大的运行时环境 Node.js 在服务器端运行 JavaScript。随着 Node.js 生态系统的不断发展,许多设计模式应运而生,它们可以提高代码组织性、可伸缩性和可维护性,同时解决常见问题。

设计模式

设计模式为 Node.js 开发中常见的许多问题提供了出色的解决方案。它们使程序员能够编写更有效、可扩展和可维护的 Node.js 代码。当开发人员遇到问题时,他们通常会求助于其中一种设计模式。Node.js 有大量的设计模式可供选择。

1. 模块模式

  • 目的:代码被封装在模块中,以管理依赖关系和作用域。
  • 实现:使用 CommonJS 或 ES6 模块系统定义和导入模块。
  • 优点:它提高了可维护性,减少了全局命名空间污染,并有助于组织代码。

示例

输出

 
8
2   

2. 单例模式

  • 目的:它确保一个类只有一个实例,并提供对其的全局访问点。
  • 实现:利用共享类的一个、跨应用程序的实例。
  • 优点:它有利于共享资源,例如配置文件和数据库连接。

示例

输出

 
true
Database connected.
Database disconnected.   

说明

  • 单例类:DatabaseConnection 确保应用程序只创建一个共享实例。
  • 验证实例:dbConnections1 和 dbConnections2 属于同一个实例。
  • 方法用法:这些 connect 和 disconnect 方法修改共享实例的状态。

3. 观察者模式

  • 目的:它的功能是允许一个主题向观察者发出其状态变化的通知。
  • 实现:通过使用回调和事件来实现观察者模式。
  • 优点:它鼓励了部件之间的松散耦合,事件驱动架构从中受益匪浅。

示例

输出

 
Observer 1 received message: Hello Observers!
Observer 2 received message: Hello Observers!
Observer 2 received message: Observer 1 has been removed   

说明

  • 主题类:它维护并更新观察者列表。
  • 作为观察者,获取主题的信息。
  • 应用:展示如何添加、删除观察者并通知它们发生的变化。

4. 工厂模式

工厂模式是一种创建型设计模式,它使用单个对象作为工厂来生产新对象。这种设计模式隐藏了实现逻辑,并鼓励在对象创建中实现灵活性和松散耦合。

  • 目标:它在不提供精确对象类信息的情况下生成对象。
  • 应用:它使用工厂函数创建对象。
  • 优点:解耦实例化过程提供了对象创建的灵活性,并简化了测试。

示例

输出

 
Thunderbird 500
Apache RTR 200    

5. 中间件模式

Express 是一款流行的 Node.js 框架,它融合了中间件的概念,这对于执行特定任务非常有帮助。中间件函数在 API 调用请求和响应之间执行操作。中间件能够访问请求和响应对象。中间件模式通过让多个中间件函数处理请求来增加代码的重用性和模块化。在 Express.js 等 Web 框架中,中间件函数通常用于在到达最终路由处理器之前处理数据解析、身份验证和日志记录等各种任务。在收到请求、响应和 next 函数后,每个中间件函数都会调用 next() 将控制权移交给下一个中间件。这种模式确保任务分配清晰,从而更容易扩展和管理功能。

  • 目的:此方法的主要目标是提供执行一系列与请求管理相关的操作。
  • 应用:通常用于 Express.js 等框架中处理 HTTP 请求的中间件函数。
  • 优点:它有助于更轻松地添加日志记录和身份验证等横切关注点,并提高了模块化和代码重用性。

示例

输出

 
Server running at https://:3000/
Hello, Middleware!
X-Powered-By: Node.js
Unauthorized   

说明

  • 它配置服务器在端口 3000 上监听,并设置 Express 应用程序。
  • logger 中间件记录每个请求的 HTTP 方法和 URL。
  • 身份验证中间件:此软件检查请求是否已通过身份验证并据此进行处理,否则返回 401 未授权错误。
  • 响应头中间件:设置个性化的响应头。
  • 使用中间件:所有中间件的功能都通过 app.use 技术应用于传入的请求。
  • 路由处理器:它指定一个路由,该路由在通过中间件操作后进行响应。

6. 代理模式

代理模式充当占位符或替代品,可以管理对对象的访问。访问控制、日志记录、延迟初始化和其他功能都可以使用此模式实现。Node.js 允许代理通过延迟创建资源密集型对象直到需要时来优化性能。例如,ProxyImage 类可以通过在首次请求时加载图像来管理对 RealImage 类的访问。通过为对象交互增加一个额外的控制层,此模式有助于资源管理。

  • 其目的是充当占位符,以便另一个对象可以管理谁可以访问它。
  • 实现:为了控制访问、验证或缓存,使用了代理对象。
  • 优点:通过限制对原始对象的访问来增强安全性和性能。

示例

输出

 
Loading photo1.jpg
Displaying photo1.jpg
Displaying photo1.jpg
Loading photo2.jpg
Displaying photo2.jpg   

说明

  • RealImage 类是执行操作的实际对象的表示。它包含 display 和 loadFromDisk 方法,这些方法模拟从磁盘加载图像。
  • ProxyImage 类是代理对象的表示,该对象管理用户对 RealImage 对象的访问。它使用延迟初始化,仅在首次调用 display 时才创建 RealImage 的实例。
  • 用法:展示了 ProxyImage 如何限制对 RealImage 的访问,确保图像仅在需要时才从磁盘加载。

7. 装饰器模式

通过使用装饰器模式,可以静态或动态地为单个对象添加行为,而不会影响同一类中其他对象的行为。此模式对于维护单一职责原则特别有用,因为它允许通过组合而不是继承来扩展功能。Node.js 装饰器允许我们为现有对象或函数添加功能。我们可以通过编写一个装饰器函数来完成此操作,该函数接受一个对象并扩展其行为。装饰器模式的常见应用包括检测、访问控制、日志记录和其他横切关注点。

  • 目标:为对象注入动态行为。
  • 实现:使用包装函数来扩展现有函数或类的功能。
  • 优点:通过允许在运行时混合行为,增强了代码的灵活性和可重用性。

示例

输出

 
Arguments: 3,4
7   

8. Promise 模式

Promise 模式是一种比回调更易读、更易维护的方法,它简化了 JavaScript 中的异步编程。Promise 代表一个可能现在、稍后或永远不存在的值。它们有三种不同的状态:pending(待定)、fulfilled(已完成)和 rejected(已拒绝)。通过使用 .then() 和 .catch(),开发人员可以链接多个异步操作,以更有效地处理错误和结果。具有保证的代码更易于阅读,错误处理得到了改进,并且回调地狱得到了减少。Promise 最初包含在 ES6 中,现在是现代 JavaScript 的基本组成部分,尤其是在处理文件操作和网络查询等异步任务时。

示例

输出

 
Data received   

说明

以下代码演示了如何在 JavaScript 中使用 Promise 模式来处理异步操作。fetchData 函数使用 setTimeout 将操作延迟一秒,并返回一个类似异步任务的新 Promise。在 Promise 内部调用 resolve("Data received") 以模拟延迟后成功检索数据。然后,调用 fetchData 函数,该函数将 "Data received" 记录到控制台,并使用 .then() 方法处理已解析的值。在此实例中,Promise 始终成功解析,但如果发生错误,.catch() 方法会处理它。与传统的基于回调的技术相比,此代码以逻辑且结构化的方式管理异步任务,使其更易于阅读和维护。

9. 立即调用函数表达式 (IIFE)

IIFE(立即调用函数表达式)是一种 JavaScript 设计模式,它允许函数在定义后立即被调用。IIFE 函数提供了一种创建新作用域而不污染全局命名空间的方法,并且它可以用单个语句调用。此模式对于封装代码和创建私有变量很有用。变量初始化、系统配置和启动逻辑是常见用途,因为它们可以隐藏内部详细信息,使其不被全局范围访问。

  • 目的:IIFE 函数是声明后立即调用的函数。
  • 封装:封装的代码保留在局部作用域内。
  • 隐私:变量和函数不能用于其设计目的以外的其他原因。

示例

输出

 
I am private   

说明

在此示例中,**privateVariable** 只能在 IIFE 内部访问,避免与其他代码冲突,并且函数被定义并立即执行。

结论

总之,模块、单例、观察者、工厂、中间件、代理、装饰器和 Promise 等顶级 Node.js 设计模式为常见的软件设计问题提供了各种独特的解决方案。与将代码组织成可重用单元的模块模式相比,单例模式确保对象只存在一次。观察者模式简化了事件驱动通信,工厂模式简化了对象创建。代理模式管理访问,而中间件模式增强了 Web 框架中的请求处理。Promise 模式有助于更好地管理异步操作,装饰器模式则用于添加动态功能。通过集体利用这些模式,Node.js 开发人员可以编写更结构化、模块化和可维护的代码,它们解决了与资源管理、异步执行和代码组织相关的各种问题。

通过理解和应用这些模式,开发人员可以利用软件设计的最佳实践来构建可扩展且可靠的应用程序。