Node.js中常用的设计模式有哪些?

news2024/11/20 1:21:33

本文由葡萄城技术团队首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

设计模式简介

设计模式是由经验丰富的程序员在日积月累中抽象出的用以解决通用问题的可复用解决方案,它提供了标准化的代码设计方案提升开发体验。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 编写高质量代码至关重要,如果您想了解更多关于前端表格控件的知识,欢迎点击这里。

扩展链接:

高级SQL分析函数-如何用窗口函数进行排名计算

3D模型+BI分析,打造全新的交互式3D可视化大屏开发方案

React + Springboot + Quartz,从0实现Excel报表自动化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1109391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谷歌浏览器修改背景色

地址栏输入:chrome://flags/ 改为Enabled即可把背景色改为黑色,亲测edge浏览器也生效

点菜MT2234

【题目】 这个题读起来真拗口,啥叫“有可能不存在”? 如果结果为yes,那就是说“没有三个人都选中的菜”, 如果结果为no,那就是说“有三个人都选中的菜” 换句话说,那就是没有一道菜被3个人都点过。 abc …

2022年亚太杯APMCM数学建模大赛D题储能系统中传热翅片的结构优化求解全过程文档及程序

2022年亚太杯APMCM数学建模大赛 D题 储能系统中传热翅片的结构优化 原题再现 高效储能技术是解决可再生能源和余热资源波动性和间歇性的核心技术。相变蓄热以其较高的储能密度和近恒温蓄热放热而得到广泛应用。固-液相变材料具有相变前后相变潜热高、体积变化小等特点&#x…

专业管理菜单的增删改、查重

1,点击专业管理菜单------查询所有专业信息列表 ①点击菜单,切换专业组件 ②切换到列表组件后,向后端发送请求到Servlet ③调用DAO层,查询数据库(sql),封装查询到的内容 ④从后端向前端做出…

律师必备软件Alpha系统,为专业律师提供高效解决方案!

Alpha法律智能操作系统由iCourt开发,是一款集大数据、市场拓展、律所管理等功能于一体的智能操作系统,它旨在通过强大的法律科技赋能法律人,更快速地获取同类型案件的办理经验,进而减轻律师工作负担、提升工作效率。目前&#xff…

python知识:从PDF 提取文本

一、说明 PDF 到文本提取是自然语言处理和数据分析中的一项基本任务,它允许研究人员和数据分析师从 PDF 文件中包含的非结构化文本数据中获得见解。Python 是一种通用且广泛使用的编程语言,它提供了多个库和工具来促进提取过程。 二、各种PDF操作库 让我…

SPSS|正负偏态的转换方法|限值1.96|反转后处理(对数法)|正态得分法|实战小练-SPSS学习(2)

目录 学习目的软件版本参考文档基础数据正负偏态的转换方法(引自《小白爱上SPSS》)正偏态数据转换方法负偏态数据转换 实战数据准备数据初探输出结果分析查看峰度、偏度查看峰度标准误差、偏度标准误差计算偏度系数和峰度系数Tips:为什么判断…

Anthropic全球上线AI语言模型Claude 2;多模态系统:融合文本和图像的新前沿

🦉 AI新闻 🚀 Anthropic全球上线AI语言模型Claude 2,编程、数学、推理能力大幅提升 摘要:Anthropic在全球正式上线了AI语言模型Claude 2。相比前代版本,Claude 2在编程、数学、推理等方面都有大幅提升,支…

MySQL学习(八)——锁

文章目录 1. 锁概述2. 全局锁2.1 全局锁的必要性2.2 语法2.3 全局锁的特点 3. 表级锁3.1 表锁3.2 元数据锁3.3 意向锁3.4 自增锁 4. 行级锁4.1 介绍4.2 记录锁4.3 间隙锁4.4 临键锁 1. 锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传…

使用Spire.PDF for Python插件从PDF文件提取文字和图片信息

目录 一、Spire.PDF插件的安装 二、从PDF文件提取文字信息 三、从PDF文件提取图片信息 四、提取图片和文字信息的进阶应用 总结 在Python中,提取PDF文件的文字和图片信息是一种常见的需求。为了满足这个需求,许多开发者会选择使用Spire.PDF插件&…

13.2测试用例

一.测试用例的四个重要要素 1.测试环境 2.操作步骤 3.测试数据 4.预期结果 注意:不需要执行结果. 5.为什么要有测试用例 a.提高测试效率,节约测试设计. b.测试用例是自动化测试的前提. 二.设计方法(黑盒测试) a.基于需求的设计方法(4,0.50) b.等价类: 依据需求,将输…

软件开发团队的成本分布

软件开发团队的成本分布通常涵盖了各种因素和人员,这些因素在项目的不同阶段会有所变化。以下是一个一般性的软件开发团队成本分布示例,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 开发…

Pysied6 ComboBox

Pysied6 ComboBox Pysied6 ComboBoxComboBox常用函数ComboBox常用信号例程ComboBox添加选项程序设置界面设置 返回选项信息添加删除选项完整程序界面程序主程序 Pyside6的ComboBox下拉列表框,可以给用户提供一系列的选项,下面就来简单了解一下Pysied6 Co…

SpringCloud-Sentinel

一、介绍 (1)提供界面配置配置服务限流、服务降级、服务熔断 (2)SentinelResource的blockHandler只处理后台配置的异常,运行时异常fallBack处理,且资源名为value时才生效,走兜底方法 二、安装…

数据分析:密度图

目前拥有的数据如图,三列分别对应瑕疵种类,对应的置信 度,x方向坐标。 现在想要做的事是观看瑕疵种类和置信度之间的关系。 要显示数据分布的集中程度,可以使用以下几种常见的图形来观察: 1、箱线图(Box P…

【工具】电脑网络连接正常,但是有些页面无法登录,如何解决?

目录 0.环境 1.背景 2.具体操作 0.环境 windows 11 64位 1.背景 我们公司的大楼无法进移动联通这种网络的线,所以网络用的是小厂的,有些小厂为了提高网络速度,会屏蔽一些网站,这就导致在工作中有些网站直接通过WIFI连接是无法访…

头歌平台——基于结构体的学生信息管理系统

第1关:学生信息管理系统 任务描述 本关任务:编写一个基于结构体得学生成绩信息管理系统。主要功能如下: 1. 用结构体存放所有数据。 2. 每个功能都用函数实现。 3. 输入10个学生的学号和三门课程的成绩。 4. 计算每个学生的总分。 5. 按总分…

头歌平台——C语言之数学运算强化练习题

第1关:逐一挑出来 任务描述 本关需要完成一个输出某个三位数各个位上的数字的小程序。 相关知识 算数运算符 %是取模运算符,获得整除后的余数。 /是通过分子除以分母,获得整除后的整数部分。 floor floor()是返回一个浮点型的整数部分…

腾讯云服务器带宽下载速度表(附上行带宽计算方法)

腾讯云服务器公网带宽下载速度计算,1M公网带宽下载速度是128KB/秒,5M带宽下载速度是512KB/s,腾讯云10M带宽下载速度是1.25M/秒,腾讯云百科txybk.com来详细说下腾讯云服务器不同公网带宽实际下载速度以及对应的上传速度对照表&…

MySQL官方文档如何查看,MySQL中文文档

这里写自定义目录标题 MySQL官方文档如何查看MySQL中文文档 MySQL官方文档如何查看 MySQL官网地址:https://dev.mysql.com/doc/ 比如这里我要找InnoDB架构 MySQL中文文档 MySQL 5.1中文文档地址:https://www.mysqlzh.com/