手记

Node.js可扩展应用的五大设计模式详解

Top 5 Node.js Design Patterns for Scalable Applications

Node.js 是构建可扩展应用程序的强大工具,但编写高效且易于维护的代码不仅仅依靠异步魔法。若要真正提高水平,你需要 设计模式(设计模式)—— 用于解决常见软件架构挑战的验证过的解决方案。

无论你是在开发微服务系统、API后端还是实时应用,使用正确的设计模式能使你的代码库更可扩展、易维护和高性能

1. 单例模式(一种软件工程中的设计模式)

你有没有想过如何在整个应用程序中共享一个对象的唯一实例?这就是单例模式所做的事情。这在比如数据库连接、缓存和日志记录等场景中特别有用,因为在这些场景中创建多个实例会比较低效。

示例:单例数据库连接

使用单例模式来管理MongoDB连接实例防止不必要的多次连接。

    class Database {  
      constructor() {  
        if (!Database.instance) {  
          this.connection = this.connect();  
          Database.instance = this;  
        }  
        return Database.instance;  
      }  

      connect() {  
        console.log("连接到数据库...");  
        return { /* 模拟的连接对象 */ };  
      }  
    }  

    const db1 = new Database();  
    const db2 = new Database();  
    console.log(db1 === db2); // true (确实是同一个实例)

用它有什么好处?

  • 避免冗余,如多个数据库连接。
  • 节省内存并优化资源利用。
2. 工厂模式

工厂模式 动态生成对象,而不指定具体的类别。这在需要根据条件实例化不同类型的对象的情形下非常有用。

例子:不同支付方式的工厂

假设你集成Stripe和PayPal。而不是直接将支付逻辑硬编码在代码中,你可以使用工厂模式来动态地选择和生成正确的支付处理器。

    class StripePayment {  
      process() {  
        console.log("正在处理通过Stripe的付款");  
      }  
    }  

    class PayPalPayment {  
      process() {  
        console.log("正在处理通过PayPal的付款");  
      }  
    }  

    class PaymentFactory {  
      static createPaymentMethod(type) {  
        if (type === "stripe") return new StripePayment();  
        if (type === "paypal") return new PayPalPayment();  
        throw new Error("无效的支付方式");  
      }  
    }  

    // 使用  
    const payment = PaymentFactory.createPaymentMethod("stripe");  
    payment.process();  

为什么用它?

  • 将对象创建与主逻辑分离开来。
  • 可以轻松添加新的支付方式,
3. 观察者模式(观察者模式,简称观察者)

观察者模式非常适合于事件驱动的应用,例如实时通知功能、消息应用或发布/订阅系统。它允许应用程序的一部分“监视”另一部分的变化,而不必紧密耦合它们。

事件触发器用于发送通知
    const EventEmitter = require("events");  

    class NotificationService extends EventEmitter {  
      sendEmail(email) {  
        console.log(`发送邮件给 ${email}`);  
        this.emit("emailSent", email);  
      }  
    }  

    const notificationService = new NotificationService();  

    // 添加观察者  
    notificationService.on("emailSent", (email) => {  
      console.log(`邮件已成功发送给 ${email}`);  
    });  

    // 使用方法  
    notificationService.sendEmail("user@example.com");

为什么要用它?

  • 非常适合实时应用场景(比如 WebSockets 和微服务架构),
  • 降低模块间的耦合度。
4. 中间件模式章

如果你曾经使用过Express.js,你已经用过中间件模式了!它将函数链接在一起,让它们依次处理请求。这让你可以单独处理认证、日志记录和验证等任务变得简单。

示例:用于身份验证的 Express 中间件插件
const express = require("express");  
const app = express();  

// 中间件函数  
const authMiddleware = (req, res, next) => {  
  if (req.headers.authorization === "Bearer my-secret-token") {  
    next(); // 继续处理下一个中间件  
  } else {  
    res.status(401).send("未授权");  
  }  
};  

app.use(authMiddleware);  

app.get("/", (req, res) => {  
  res.send("欢迎认证用户!");  
});  

app.listen(3000, () => console.log("服务器运行在3000端口"));

为什么要用它?

  • 清晰的职责划分。
  • 可重用的日志记录、身份验证和数据验证逻辑。
5. 代理模式 (The Proxy Pattern)

代理模式作为另一个对象的代理,控制对它的访问。这在缓存数据、限制频率和处理API请求等方面特别有用,可以帮助减少不必要的计算。

注释:API调用缓存示例
示例:API调用缓存

注释:此处选择使用"API调用缓存"来更贴合技术口语化表达,并且在注释中标明了这是关于"缓存API调用"的示例。

    class API {  
      fetchData() {  
        console.log("正在从API获取数据...");  
        return { data: "API的响应" };  
      }  
    }  

    class CachedAPI {  
      constructor() {  
        this.api = new API();  
        this.cache = null;  
      }  

      fetchData() {  
        if (!this.cache) {  
          this.cache = this.api.fetchData();  
        }  
        return this.cache;  
      }  
    }  

    // 示例用法  
    const api = new CachedAPI();  
    console.log(api.fetchData()); // 从API获取数据  
    console.log(api.fetchData()); // 返回缓存里的数据

为什么要用它?

  • 减少 API 调用,提升性能。
  • 非常适合缓存那些资源消耗大的操作。
收尾

设计模式是构建可扩展的 Node.js 应用的变革者。这里做个快速回顾:

→ 单例 — 整个应用中只实例化一次(例如,数据库连接)。
→ 工厂 — 根据需求动态创建对象(例如,不同的支付处理器)。
→ 观察者 — 事件驱动机制(例如,通知、WebSocket)。
→ 中间件 — 可链接的中间件逻辑(例如,Express.js 中间件)。
→ 代理 — 控制对资源的访问(例如,缓存 API 响应)。

通过使用这些模式,你可以编写更干净、更可扩展,且更高效的 Node.js 应用程序。

你也可能喜欢这样的:

1)如何让网站运行更快更流畅?

2)使用Artillery做负载测试:准备应对Node.js应用程序的高流量峰值

3)软件开发面试中最常被问到的十个问题及如何回答,

4)高级JavaScript Promise面试问题

5)数据库索引是什么,你知道为什么它很重要吗?

6) AI能否改变交易格局?

7)部署管道的目的是什么?

8) 基于令牌的身份验证方法:如何在现代应用程序中选择JWT和Paseto

9) Node.js 中防止滥用的 API 速率限制策略 — 面向高流量 API https://blog.arunangshudas.com/api-rate-limiting-and-abuse-prevention-strategies-in-node-js-for-high-traffic-apis/

更多博客请点阅此处

在评论区分享一下你的经验,让我们一起聊聊怎么解决这些问题吧!

关注我领英

0人推荐
随时随地看视频
慕课网APP