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 (确实是同一个实例)
用它有什么好处?
- 避免冗余,如多个数据库连接。
- 节省内存并优化资源利用。
工厂模式 动态生成对象,而不指定具体的类别。这在需要根据条件实例化不同类型的对象的情形下非常有用。
例子:不同支付方式的工厂假设你集成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();
为什么用它?
- 将对象创建与主逻辑分离开来。
- 可以轻松添加新的支付方式,
观察者模式非常适合于事件驱动的应用,例如实时通知功能、消息应用或发布/订阅系统。它允许应用程序的一部分“监视”另一部分的变化,而不必紧密耦合它们。
事件触发器用于发送通知 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 和微服务架构),
- 降低模块间的耦合度。
如果你曾经使用过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端口"));
为什么要用它?
- 清晰的职责划分。
- 可重用的日志记录、身份验证和数据验证逻辑。
代理模式作为另一个对象的代理,控制对它的访问。这在缓存数据、限制频率和处理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 应用程序。
你也可能喜欢这样的:
2)使用Artillery做负载测试:准备应对Node.js应用程序的高流量峰值
6) AI能否改变交易格局?
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/
更多博客请点阅此处
在评论区分享一下你的经验,让我们一起聊聊怎么解决这些问题吧!
关注我领英