Node.js中常用的设计模式有哪些?
本文由葡萄城技术团队首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
设计模式简介
设计模式是由经验丰富的程序员在日积月累中抽象出的用以解决通用问题的可复用解决方案,它提供了标准化的代码设计方案提升开发体验。Node.js 作为一款用来构建可扩展高性能应用的流行平台,自然也遵循设计模式解决通用问题。本文中,我们将讨论 Node.js 中设计模式的重要性并提供一些代码示例。

构建 Node.js 应用为何需要设计模式
设计模式为软件开发提供了一套标准化的解决方案。构建 Node.js 应用时,善用设计模式能够帮助开发者提升代码质量,节约开发时间,减少出错几率。同时也方便开发人员之间的沟通交流。

示例代码
单例模式
该模式用来保证特定的类在整个应用中只能创建唯一实例。Node.js 中,单例模式可以保证在同一个应用中,每个模块只有唯一实例。
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
}
// Your code here
}
module.exports = Singleton;
工厂模式
工厂模式用来在不暴露实现逻辑的情况下创建对象。在 Node.js 中,使用工厂模式可以根据用户输入创建不同类型的实例。
class Car {
constructor(name) {
this.name = name;
}
drive() {
console.log(`Driving ${this.name}`);
}
}
class CarFactory {
static create(name) {
return new Car(name);
}
}
const car1 = CarFactory.create("BMW");
const car2 = CarFactory.create("Audi");
car1.drive(); // Driving BMW
car2.drive(); // Driving Audi
观察者模式
观察者模式通过维护一个被观察对象列表,实现当对象发生改变时发出通知。在 Node.js中,该设计模式用来管理事件和回调。
class EventObserver {
constructor() {
this.observers = [];
}
subscribe(fn) {
this.observers.push(fn);
}
unsubscribe(fn) {
this.observers = this.observers.filter(subscriber => subscriber !== fn);
}
notify(data) {
this.observers.forEach(observer => observer(data));
}
}
const eventObserver = new EventObserver();
eventObserver.subscribe(data => console.log(`Subscribed to ${data}`));
eventObserver.notify("some data");
依赖注入模式
在本案例中,定义了一个依赖database 对象的UserService 类。通过将 database 传给 UserService 的构造函数,实现在不修改 UserService 的前提下操作不同数据库对象。
class UserService {
constructor(database) {
this.database = database;
}
getUser(id) {
return this.database.query(`SELECT * FROM users WHERE id = ${id}`);
}
}
module.exports = UserService;
Promise 模式
在本案例中,通过 fs.promises 模块异步读取文件。readFile 函数返回一个 promise 对象,该 promise对象成功时可以通过 then 方法获取文件内容,失败时可以通过 catch 方法获取错误信息。
const fs = require('fs').promises;
function readFile(filePath) {
return fs.readFile(filePath, 'utf8');
}
readFile('example.txt')
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
Node.js 内建模块中的设计模式
默认情况下,Node.js 本身在其功能中不依赖任何特定的设计模式,但它提供了遵循常见设计模式的内置模块。Node.js 中一些常用的设计模式包括:
模块模式
Node.js 默认使用模块模式将代码组织成可复用、可维护的模块。在 Node.js 中,每个文件都被视为一个模块,开发人员可以使用 require 和 module.exports 语句在文件之间导出或导入代码。
const fs = require('fs');
// 异步读取文件
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 同步读取文件
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
// 写入文件
fs.writeFile('file.txt', 'Hello, World!', (err) => {
if (err) throw err;
console.log('文件已写入');
});
事件驱动模式
Node.js 使用事件驱动模式来处理 I/O 操作,如向文件或网络套接字读取和写入数据。事件驱动模式基于观察者模式,允许开发人员创建事件发射器,以便在某些事件发生时通知侦听器。
// 模块定义
const myModule = (function () {
// 私有成员
const privateVar = 'Hello, World!';
function privateMethod() {
console.log(privateVar);
}
// 公有成员
return {
publicMethod: function () {
privateMethod();
},
publicVar: 'I am public'
};
})();
// 使用模块
myModule.publicMethod(); // 输出 'Hello, World!'
console.log(myModule.publicVar); // 输出 'I am public'
回调模式
Node.js 使用回调模式来处理异步操作,如读写文件或网络请求。回调模式基于观察者模式,允许开发人员将函数作为参数传递,以便在操作完成时执行。
function fetchData(callback) {
// 模拟异步数据获取
setTimeout(() => {
const data = 'Hello, World!';
callback(null, data); // 第一个参数为错误对象,第二个参数为返回的数据
}, 2000);
}
function processData(err, data) {
if (err) {
console.error('出错了:', err);
return;
}
console.log('处理数据:', data);
}
fetchData(processData);
中间件模式
中间件是 Express.js 等 Node.js 框架中常用的设计模式。中间件函数是在管道中执行的函数,其中每个函数都可以在将请求或响应对象传递到下一个函数之前修改它们。中间件可用于身份验证、日志记录、错误处理等任务。
// 中间件函数1
function middleware1(req, res, next) {
console.log('执行中间件1');
// 在这里可以对 req 和 res 进行处理
next(); // 调用 next() 将控制权传递给下一个中间件
}
// 中间件函数2
function middleware2(req, res, next) {
console.log('执行中间件2');
// 在这里可以对 req 和 res 进行处理
next(); // 调用 next() 将控制权传递给下一个中间件
}
// 最终处理函数
function finalHandler(req, res) {
console.log('执行最终处理函数');
// 在这里进行最终的请求处理和响应
res.end('Hello, World!');
}
// 使用中间件
function handleRequest(req, res) {
middleware1(req, res, () => {
middleware2(req, res, () => {
finalHandler(req, res);
});
});
}
// 创建服务器并处理请求
const http = require('http');
const server = http.createServer(handleRequest);
server.listen(3000, 'localhost', () => {
console.log('服务器已启动');
});
依赖注入模式
依赖注入(DI)模式是一种用于管理对象之间依赖关系的设计模式。在 Node.js 中,DI 可用于将依赖项注入到模块中,使它们更加模块化和可重用。DI 可以使用构造函数注入、属性注入或方法注入等技术来实现。
// 用户服务模块
class UserService {
constructor() {
this.users = [];
}
addUser(user) {
this.users.push(user);
}
getUsers() {
return this.users;
}
}
// 用户控制器模块(依赖于用户服务模块)
class UserController {
constructor(userService) {
this.userService = userService;
}
addUser(user) {
this.userService.addUser(user);
}
getUsers() {
return this.userService.getUsers();
}
}
// 使用依赖注入创建用户控制器实例
const userService = new UserService();
const userController = new UserController(userService);
// 在用户控制器中添加用户并获取用户列表
userController.addUser('John');
userController.addUser('Mary');
console.log(userController.getUsers()); // 输出:['John', 'Mary']
Promise模式
Promise模式是一种设计模式,用于以更结构化和类似同步的方式处理异步操作。Promise 是表示异步操作最终完成或失败的对象,允许开发人员通过将异步操作连接在一起来编写更具可读性和可维护性的代码。
// 使用 Promise 封装异步函数
function getUserById(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const user = { id, name: 'John' };
resolve(user);
}, 1000);
});
}
// 调用异步函数并使用 Promise 链式调用处理结果
getUserById(1)
.then(user => {
console.log(user);
return getUserById(2);
})
.then(user => {
console.log(user);
})
.catch(err => {
console.error(err);
});
总结
设计模式提供了一种结构化方法来解决 Node.js 中的常见编程问题。它们帮助开发人员编写更好、可维护和可扩展的代码。设计模式还为开发人员之间的交流提供了“标准词汇”。设计模式对于使用 Node.js 编写高质量代码至关重要,如果您想了解更多关于前端表格控件的知识,欢迎点击这里。
扩展链接:
React + Springboot + Quartz,从0实现Excel报表自动化
Node.js中常用的设计模式有哪些?的更多相关文章
- node.js中常用的fs文件系统
fs文件系统模块对于系统文件及目录进行一些读写操作. 模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync(). 异步的 ...
- js 中常用的设计模式
常用的设计模式: 工厂方法模式.单例模式.适配器模式.组合模式.迭代子模式 (23种设计模式) 总体来说设计模式分为三大类: ①创建型模式 共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原 ...
- Node.js中的模块化
每天一篇文章来记录记录自己的成长吧.大二,该静心了.加油~ 好了,废话不多说,今天说说nodejs中的模块化.(注:此文为自己对书nodejs实战的总结) nodejs一个重要的特性就是模块化,模块就 ...
- Node.js:常用工具util
概要:本篇博客的主要内容是介绍node.js的常用工具util. 1.util.inherits util.inherits(constructor,superConstructor)是一个实现对象间 ...
- Node.js中环境变量process.env详解
Node.js中环境变量process.env详解process | Node.js API 文档http://nodejs.cn/api/process.html官方解释:process 对象是一个 ...
- node.js中的回调
同步和阻塞:这两个术语可以互换使用,指的是代码的执行会在函数返回之前停止.如果某个操作阻塞,那么脚本就无法继续,这意味着必须等待. 异步和非阻塞:这两个术语可以互换使用,指的是基于回调的.允许脚本并行 ...
- Cookie和Session在Node.JS中的实践(二)
Cookie和Session在Node.JS中的实践(二) cookie篇在作者的上一篇文章Cookie和Session在Node.JS中的实践(一)已经是写得算是比较详细了,有兴趣可以翻看,这篇是s ...
- 理解 Node.js 中 Stream(流)
Stream(流) 是 Node.js 中处理流式数据的抽象接口. stream 模块用于构建实现了流接口的对象. Node.js 提供了多种流对象. 例如,对 HTTP 服务器的request请求和 ...
- 前端走进机器学习生态,在 Node.js 中使用 Python
这次给大家带来一个好东西,它的主要用途就是能让大家在 Node.js 中使用 Python 的接口和函数.可能你看到这里会好奇,会疑惑,会不解,我 Node.js 大法那么好,干嘛要用 Python ...
- js中常用追加元素的几种方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- 【Shell】ps 命令
ps 命令 Linux ps (英文全拼:process status)命令用于显示当前进程的状态,类似于 windows 的任务管理器. 1. ps 常用的命令 ps -aux #显示所有进程信息 ...
- 2.融合进阶:Stacking与Blending
1 堆叠法Stacking 1.1 堆叠法的基本思想 堆叠法Stacking是近年来模型融合领域最为热门的方法,它不仅是竞赛冠军队最常采用的融合方法之一,也是工业中实际落地人工智能时会考虑的方案之一. ...
- 一个Web项目实现多个数据库存储数据并相互切换
1.使用场景 多数据源使用场景一般为: 主从数据库切换 读写分离 兼容旧库 2.具体实现 实现原理 Spring2.x的版本中采用Proxy模式,就是在方案中实现一个虚拟的数据源,并且用它来封装数据源 ...
- Libvirtd networks -- 为libvirtd 中虚拟机指定ip遇到的问题
backgroup 为libvirtd 中虚拟机指定ip,操作如下: virsh --connect qemu:///system dumpxml vm01 | grep "mac addr ...
- Llama2 论文中译版——开放式基础和微调聊天模型
Llama 2:开放式基础和微调聊天模型 写在前头 因为最近一直在使用 LLM 工具,所以在学习 Llama 2:开放式基础和微调聊天模型 这篇论文的期间,顺手将内容翻译了过来. 整片译文是由 Cha ...
- MySQL_Explain详解
当我们在工作中面临SQL优化的问题时,熟练掌握适合的工具,就能使事半功倍,提高工作效率.其中,EXPLAIN工具就是一种常用且高效的SQL优化工具. EXPLAIN关键字的使用方法是,在select语 ...
- 从浅入深了解.NET Core MVC 2.x全面教程【第二章】
二.Logging 1.诊断中间件 命名空间:Microsoft.AspNetCore.Diagnostics 报告信息并处理异常 2.诊断中间件 UseDeveloperExceptionPage: ...
- 【pytorch】ResNet源码解读和基于迁移学习的实战
"工欲善其事,必先利其器",掌握ResNet网络有必要先了解其原理和源码.本文分别从原理.源码.运用三个方面出发行文,先对ResNet原理进行阐述,然后对pytorch中的源码进行 ...
- Amiya 前端UI
最近在使用一个基于Ant Design 二次封装的组件 Git文档地址 Index - Amiya (gitee.io)
- 我也来扒一扒python的内存回收机制!
python的内存回收是面试中经常会问到一个问题,今天我来给大家深度剖析下python的内存回收和缓存机制 1.引用计数器 我们知道,python是通过引用计数器来做内存回收的,下面我们来重点讲下引用 ...