Padrões de Design em JavaScript com exemplos para Node.js
Padrões de design são soluções comprovadas para problemas comuns de desenvolvimento. Em JavaScript, especialmente no ambiente Node.js, eles ajudam a criar código escalável, sustentável e reutilizável. Neste artigo, vamos explorar quatro padrões principais: Singleton, Factory, Observer e Module, com exemplos práticos.
1. Padrão Singleton
Singleton garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a ela. Em Node.js, isso é frequentemente usado para conexão com banco de dados ou configuração da aplicação.
Implementação Singleton em Node.js
class Database { constructor() { if (Database.instance) { return Database.instance; } this.connection = null; Database.instance = this; }
async connect(uri) { // Simulação de conexão com BD this.connection = `Connected to ${uri}`; console.log(this.connection); }
getConnection() { return this.connection; }}
// Usoconst db1 = new Database();const db2 = new Database();
console.log(db1 === db2); // true
db1.connect('mongodb://localhost:27017/myapp');console.log(db2.getConnection()); // "Connected to mongodb://localhost:27017/myapp"Quando usar: Gerenciamento de pool de conexões, logger global, sistemas de cache.
2. Padrão Factory
Factory permite criar objetos sem especificar a classe concreta. Ele centraliza a lógica de criação de objetos, simplificando a manutenção do código.
Implementação Factory para validadores
class EmailValidator { validate(value) { return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value); }}
class PhoneValidator { validate(value) { return /^\\+?[\\d\\s\\-()]{7,15}$/.test(value); }}
class ValidatorFactory { createValidator(type) { switch (type) { case 'email': return new EmailValidator(); case 'phone': return new PhoneValidator(); default: throw new Error('Unknown validator type'); } }}
// Usoconst factory = new ValidatorFactory();const emailValidator = factory.createValidator('email');
console.log(emailValidator.validate('test@example.com')); // trueconsole.log(emailValidator.validate('invalid')); // falseQuando usar: Criação de objetos complexos, trabalho com diferentes formatos de dados (JSON, XML, YAML), geração de componentes de UI.
3. Padrão Observer
Observer cria um mecanismo de assinatura, permitindo que objetos (observadores) acompanhem mudanças em outro objeto (sujeito). Em Node.js, esse padrão é integrado através da classe EventEmitter.
Implementação Observer com EventEmitter
const EventEmitter = require('events');
class NewsPublisher extends EventEmitter { publishArticle(title) { console.log(`📰 Artigo publicado: ${title}`); this.emit('article', { title, date: new Date() }); }}
class Subscriber { constructor(name) { this.name = name; }
receiveArticle(article) { console.log(`🔔 ${this.name} recebeu: "${article.title}"`); }}
// Usoconst publisher = new NewsPublisher();const subscriber1 = new Subscriber('Ana');const subscriber2 = new Subscriber('João');
publisher.on('article', (data) => subscriber1.receiveArticle(data));publisher.on('article', (data) => subscriber2.receiveArticle(data));
publisher.publishArticle('Padrões de Design em JavaScript');// Saída:// 📰 Artigo publicado: Padrões de Design em JavaScript// 🔔 Ana recebeu: "Padrões de Design em JavaScript"// 🔔 João recebeu: "Padrões de Design em JavaScript"Quando usar