Patrones de diseño en Node.js

1

Qué es Node.js y cómo impulsa tu negocio

2

Patrones de diseño esenciales en Node.js

3

Patrón Singleton y Factory en JavaScript

4

Implementación práctica de Singleton y Factory en JavaScript

5

Implementación del patrón Observer con EventEmitter en Node.js

6

Implementación de Middlewares en Node.js sin Express

7

Decorators e inyección de dependencias en JavaScript

Flujo de Datos con Node.js

8

Aprende qué son Buffer y Streams en Node.js

9

Cómo utilizar streams y pipelines en Node.js

10

Cómo funciona el Event Loop en Node.js

11

Qué es Libuv y cómo maneja la asincronía en Node.js

12

Estrategias para ejecutar código asíncrono en Node.js

Debugging y Diagnóstico en Node.js

13

Cómo utilizar el Debugger en Node.js para solucionar problemas

14

Uso de Diagnostic Channels en Node.js para observabilidad y diagnóstico

15

Instrumentación y métricas clave en performance para aplicaciones Node.js

16

Control de errores globales y manejo de señales en Node.js

17

Implementación Eficiente de Logs con Pino en Node.js

Performance en Node.js

18

Análisis del event loop en aplicaciones Node.js usando Nsolid

19

Cómo Diagnosticar y Solucionar Memory Leaks en Aplicaciones Node.js

20

Optimizar rendimiento en Node.js con Worker Threads y Child Processes

21

Optimiza y Escala Aplicaciones Node.js con Técnicas de Caching

Creando CLIs con Node.js

22

Cómo crear aplicaciones CLI con Node.js

23

Cómo Crear un CLI con Minimist y Manejar Argumentos en Node.js

24

Creación de un CLI con Node.js y Google Generative AI

25

Creación de Chat con IA usando CLI en Node

26

Cómo Crear e Instalar tu Propio CLI de Node con npm

You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

2 Días
17 Hrs
40 Min
48 Seg

Implementación práctica de Singleton y Factory en JavaScript

4/26
Resources

Combining design patterns such as Singleton and Factory allows solving everyday situations in software development, ensuring efficiency and clarity in the creation and handling of objects. In this practical example, you will learn how to integrate these two patterns in JavaScript, creating a useful system to handle logs in different contexts such as console and file.

What is a Singleton and how to implement it in JavaScript?

The Singleton pattern ensures that a class has a single instance throughout the application, facilitating control over specific resources, such as logs or database connections.

To create a Singleton in JavaScript:

  • Define a class, in this case Logger, with a static method that checks if an instance already exists, and if not, creates it.
  • Create an array within the class to store single logs.
  • It implements specific methods, such as log to add messages with a timestamp and getLogs that returns the complete array of logs.

How does the Factory pattern work in combination with the Singleton?

The Factory pattern gives you the facility to create objects of different types according to your specific implementation needs. When you combine Factory with Singleton:

  • You create a log factory file(loggerFactory.js) that instantiates different logger (such as Console or File).
  • In each specific class, such as ConsoleLogger, you encapsulate the Singleton instance of Logger to ensure efficient resource sharing.
  • You use the Factory via a static CreateLogger method to easily generate instances adapted to the required type (console or file).

How to carry out this practical implementation?

The clear and simple procedure to implement this effective combination in JavaScript is:

  1. Create the file structure, with logger.js as Singleton and loggerFactory.js as Factory pattern.
  2. Clearly define each class involved as ConsoleLogger and FileLogger, each with individual tailored logic.
  3. Use an index.js file to import, instantiate and concretely use these objects.
  4. Troubleshoot possible implementation errors, such as correctly defining the necessary instances when importing objects from modules.

This practical exercise also presents you with an interesting challenge to deepen your learning. Try to complete the implementation so that the FileLogger actually stores the messages in a real file and share your achievements in the comments.

Contributions 4

Questions 0

Sort by:

Want to see more contributions, questions and answers from the community?

Esta es mi solución utilizando ES Modules: ```js import fs from 'node:fs'; import path from 'node:path'; import url from 'node:url'; import Logger from './logger.js'; const loggerInstance = new Logger(); const __filename = url.fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); class ConsoleLogger { constructor() { this.logger = loggerInstance; } log(message) { console.log('Using ConsoleLogger'); console.log(`ConsoleLogger: ${message}`); this.logger.log(message); } } class FileLogger { constructor() { this.filePath = path.join(__dirname, 'log.txt'); this.logger = loggerInstance; } log(message) { this.logger.log(message); const logTimestamp = new Date().toISOString(); const loggedMessage = `${logTimestamp}: ${message}`; fs.appendFileSync(this.filePath, `${loggedMessage}\n`); } } class LoggerFactory { static createLogger(type) { switch (type) { case 'console': return new ConsoleLogger(); case 'file': return new FileLogger(); default: throw new Error('Invalid Logger type'); } } } export default LoggerFactory; ```
Si quisiéramos escribir en un archivo los logs provenientes del `FileLogger` podríamos hacer lo siguiente:const fs = require('fs');const path = require('path');const Logger = require('./logger'); const loggerInstance = new Logger(); // Singleton instance class ConsoleLogger {  constructor() {    this.logger = loggerInstance;  }   log(message) {    this.logger.log(message);  }} class FileLogger {  constructor(filePath = path.join(\_\_dirname, 'logs.txt')) {    this.logger = loggerInstance;    this.filePath = filePath;  }   log(message, level = 'info') {    this.logger.log(message);     const timestamp = new Date().toISOString();    const formattedMessage = `\[${timestamp}] \[${level.toUpperCase()}] ${message}\n`;     fs.appendFileSync(this.filePath, formattedMessage, 'utf8');    this.logger.log(message, level); // Registrar en el logger base  }} class LoggerFactory {  static createLogger(type) {    switch (type) {      case 'console':        return new ConsoleLogger();      case 'file':        return new FileLogger();      default:        throw new Error('Invalid logger type');    }  }} module.exports = LoggerFactory; ```js const fs = require('fs'); const path = require('path'); const Logger = require('./logger'); const loggerInstance = new Logger(); // Singleton instance class ConsoleLogger { constructor() { this.logger = loggerInstance; } log(message) { this.logger.log(message); } } class FileLogger { constructor(filePath = path.join(__dirname, 'logs.txt')) { this.logger = loggerInstance; this.filePath = filePath; } log(message, level = 'info') { this.logger.log(message); const timestamp = new Date().toISOString(); const formattedMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}\n`; fs.appendFileSync(this.filePath, formattedMessage, 'utf8'); this.logger.log(message, level); // Registrar en el logger base } } class LoggerFactory { static createLogger(type) { switch (type) { case 'console': return new ConsoleLogger(); case 'file': return new FileLogger(); default: throw new Error('Invalid logger type'); } } } module.exports = LoggerFactory; ```
El patrón Factory ofrece varias ventajas, como: 1. **Desacoplamiento**: Permite separar la creación de objetos de su uso, facilitando la modificación sin afectar al resto del código. 2. **Flexibilidad**: Puedes añadir nuevos tipos de objetos sin modificar el código existente, solo ajustando la fábrica. 3. **Facilidad en pruebas**: Facilita el uso de mocks y stubs, lo que mejora las pruebas unitarias al poder controlar qué objetos se crean. 4. **Consistencia**: Asegura que los objetos se creen de manera uniforme, siguiendo un proceso estandarizado. Estos beneficios ayudan en la escalabilidad y mantenimiento del código, esenciales en aplicaciones complejas.
```js //con estas lineas de codigo creamos un archivo sincrono const fs = require('node:fs') class FileLogger{ constructor(){ this.logger = loggerInstance } log(message){ fs.writeFileSync('example.txt',message); console.log('Usando Filelogger') console.log(`Filelogger: ${message}`) this.logger.log(message) } } ```