TechLead

Patrones de Diseño

Patrones comunes de JavaScript: Singleton, Factory, Observer, Module y más

Patrones de Diseño en JavaScript

Los patrones de diseño son soluciones reutilizables a problemas comunes de programación. Proporcionan enfoques probados para estructurar código, haciéndolo más mantenible, escalable y fácil de entender.

Categorías de Patrones

  • Creacionales — Creación de objetos (Singleton, Factory)
  • Estructurales — Composición de objetos (Decorator, Facade)
  • Comportamiento — Comunicación de objetos (Observer, Strategy)

Patrón Singleton

Asegura que solo exista una instancia de una clase:

// Singleton con Módulo ES6 (enfoque más simple)
class Database {
  constructor() {
    this.connection = null;
  }
  
  connect(url) {
    if (!this.connection) {
      this.connection = `Conectado a ${url}`;
    }
    return this.connection;
  }
}

export const database = new Database();

Patrón Factory

Crea objetos sin exponer la lógica de instanciación:

function createUser(type) {
  const baseUser = {
    createdAt: new Date(),
    isActive: true,
  };
  
  const types = {
    admin: { role: "admin", permissions: ["read", "write", "delete"] },
    editor: { role: "editor", permissions: ["read", "write"] },
    viewer: { role: "viewer", permissions: ["read"] },
  };
  
  return { ...baseUser, ...types[type] };
}

const admin = createUser("admin");

Patrón Observer (Pub/Sub)

Los objetos se suscriben a eventos y son notificados cuando ocurren:

class EventEmitter {
  constructor() {
    this.events = {};
  }
  
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
    return () => this.off(event, listener);
  }
  
  emit(event, data) {
    if (!this.events[event]) return;
    this.events[event].forEach(listener => listener(data));
  }
}

const emitter = new EventEmitter();
emitter.on("userLoggedIn", (user) => {
  console.log(`Bienvenido, ${user.name}!`);
});
emitter.emit("userLoggedIn", { name: "Alice" });

Patrón Strategy

Define una familia de algoritmos e intercambiarlos:

const paymentStrategies = {
  creditCard: (amount) => {
    console.log(`Pagado $${amount} con tarjeta`);
    return { success: true, method: "creditCard" };
  },
  paypal: (amount) => {
    console.log(`Pagado $${amount} vía PayPal`);
    return { success: true, method: "paypal" };
  },
};

class PaymentProcessor {
  constructor(strategy) {
    this.strategy = strategy;
  }
  
  pay(amount) {
    return this.strategy(amount);
  }
}

const processor = new PaymentProcessor(paymentStrategies.creditCard);
processor.pay(100);

💡 Puntos Clave

  • Singleton — Instancia única (los módulos ES son singletons naturales)
  • Factory — Creación centralizada de objetos
  • Observer — Pub/sub para comunicación dirigida por eventos
  • Strategy — Algoritmos intercambiables
  • Decorator — Agregar comportamiento sin modificar el original
  • Facade — Simplificar interfaces complejas