DevHub Global Solutions | Educativo

Patrones de diseño: Singleton, Observer y Factory

Domina los patrones de diseño fundamentales en JavaScript para crear código robusto, mantenible y escalable. Este artículo explora implementaciones prácticas de Singleton, Observer y Factory con ejemplos reales y casos de uso.
Patrones de diseño: Singleton, Observer y Factory
Diagrama de relaciones entre patrones Singleton, Observer y Factory

Singleton: Instancia Única

Garantiza una sola instancia globalmente accesible:

Instancia única

Solo una instancia en toda la aplicación

Acceso global

Punto de acceso centralizado

Casos de uso

Conexiones DB, Configuración, Logging

class DatabaseConnection {
  constructor() {
    if (DatabaseConnection.instance) {
      return DatabaseConnection.instance;
    }
    
    this.connection = this.createConnection();
    DatabaseConnection.instance = this;
  }
  
  createConnection() {
    // Lógica compleja de conexión
    console.log('Conexión establecida');
    return { status: 'connected' };
  }
  
  query(sql) {
    // Ejecutar consulta
    return `Resultados de: ${sql}`;
  }
}

// Uso
const db1 = new DatabaseConnection();
const db2 = new DatabaseConnection();
console.log(db1 === db2); // true

En JavaScript moderno, usar módulos ES6 suele ser mejor alternativa que Singleton clásico

Observer: Comunicación por Eventos

Patrón publicador-suscriptor para comunicación descentralizada:

class Subject {
  constructor() {
    this.observers = [];
  }
  
  subscribe(observer) {
    this.observers.push(observer);
  }
  
  unsubscribe(observer) {
    this.observers = this.observers.filter(obs => obs !== observer);
  }
  
  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }
  
  update(data) {
    console.log(`${this.name} recibió: ${data}`);
  }
}

// Uso
const notificador = new Subject();

const obs1 = new Observer('Suscriptor 1');
const obs2 = new Observer('Suscriptor 2');

notificador.subscribe(obs1);
notificador.subscribe(obs2);

notificador.notify('Mensaje importante');

Factory: Creación Dinámica

Centraliza la creación de objetos sin exponer lógica interna:

class VehiculoFactory {
  static crearVehiculo(tipo, config) {
    switch(tipo) {
      case 'auto':
        return new Auto(config);
      case 'moto':
        return new Moto(config);
      case 'camion':
        return new Camion(config);
      default:
        throw new Error('Tipo de vehículo inválido');
    }
  }
}

class Auto { constructor({modelo, color}) { /* ... */ } }
class Moto { constructor({modelo, cilindrada}) { /* ... */ } }

// Uso
const miAuto = VehiculoFactory.crearVehiculo('auto', {
  modelo: 'Sedán',
  color: 'rojo'
});
Tipo Factory Implementación Cuando usar
Simple Factory Función que retorna objetos Creación básica
Factory Method Clase con método de creación Creación con lógica
Abstract Factory Fábrica de fábricas Familias de objetos relacionados

Casos Reales en Desarrollo Web

Aplicación de patrones en proyectos modernos:

Singleton

Stores globales en aplicaciones React

Observer

Sistemas de eventos en Vue, Redux

Factory

Creación de componentes dinámicos

// Observer en React con Context API
const ThemeContext = React.createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Componentes suscritos
const Header = () => {
  const { theme } = useContext(ThemeContext);
  return <header className={`header-${theme}`}>...</header>;
};
CM

Sobre el autor

Arquitecto de software con 15 años de experiencia. Autor de 'Patrones de Diseño en JavaScript Moderno' y conferenciante internacional.