Patrón de diseño Singleton

Cómo se implementa el patrón de diseño Singleton en JavaScript.

patron-diseño-singleton

El patrón Singleton es uno de los patrones de diseño más conocidos en desarrollo de software, concretamente en los lenguajes orientados a objetos. Sirve para asegurarnos de que una clase tenga una única instancia y proporcionar un único punto de acceso global a ella.

¿Por qué usar este patrón en JavaScript?

En muchas aplicaciones web o aplicaciones Node.js, hay ciertos objetos que no deberían duplicarse. Configuraciones globales, conexiones a servicios externos, loggers, etc.

Crear una nueva instancia cada vez puede ser innecesario e incluso perjudicial si el objeto mantiene un estado compartido.

Cómo implementarlo

Existen varias formas de crear un Singleton en JavaScript. Veamos un ejemplo:

class Config {
constructor() {
if (Config._instancia) {
return Config._instancia;
}
this.opciones = {
modo: 'producción',
version: '1.0.0'
};
Config._instancia = this;
}
obtener(key) {
return this.opciones[key];
}
}
const instancia1 = new Config();
const instancia2 = new Config();
console.log(instancia1 === instancia2); // true

El constructor comprueba si ya existe una instancia y, si es así, la devuelve en lugar de crear una nueva. De esta manera, la clase actúa como un Singleton.

Precauciones

El uso del patrón Singleton también implica algunos puntos a tener en cuenta:

  • Dependencias ocultas: otros módulos acceden directamente a una instancia compartida, lo que reduce la visibilidad y dificulta las pruebas.
  • Estado global mutable: si la instancia guarda estado interno, cualquier cambio afecta a todos los consumidores.
  • Menor flexibilidad: cambiar la implementación de un Singleton puede tener efectos colaterales en toda la aplicación.

En muchos casos, puede ser más conveniente inyectar dependencias o crear instancias explícitamente y compartirlas solo donde sea necesario.

Conclusión

El patrón Singleton en JavaScript es fácil de implementar, tanto con clases como con módulos. Su uso tiene sentido cuando queremos garantizar una única instancia compartida, como en el caso de una configuración global o un logger.

No obstante, es importante no abusar de este patrón. Puede introducir acoplamientos innecesarios y dificultar la evolución del código. Siempre conviene evaluar si una instancia compartida es realmente necesaria o si puede resolverse de otra forma.