Que padrões de design você usou na prática?
sobes.tech IA
Resposta da IA
Na prática, apliquei os seguintes padrões de projeto:
-
Método de Fábrica (Factory Method): Para criar objetos de diferentes tipos sem especificar a classe concreta de criação. Útil ao trabalhar com várias fontes de dados ou configurações.
// Exemplo de uso do método de fábrica class DataReader { read() { throw new Error("Método não implementado"); } } class FileReader extends DataReader { read() { console.log("A ler dados do ficheiro..."); } } class NetworkReader extends DataReader { read() { console.log("A ler dados da rede..."); } } class DataReaderFactory { createReader(type) { switch (type) { case "file": return new FileReader(); case "network": return new NetworkReader(); default: throw new Error("Tipo de leitor desconhecido"); } } } const factory = new DataReaderFactory(); const fileReader = factory.createReader("file"); fileReader.read(); -
Singleton (Singleton): Para garantir que apenas uma instância de uma classe exista e fornecer um ponto de acesso global a ela. Frequentemente usado para gestores de configuração ou ligações a bases de dados.
// Exemplo de uso do singleton class ConfigManager { constructor() { if (ConfigManager.instance) { return ConfigManager.instance; } this.config = {}; ConfigManager.instance = this; } setConfig(key, value) { this.config[key] = value; } getConfig(key) { return this.config[key]; } } const instance1 = new ConfigManager(); const instance2 = new ConfigManager(); console.log(instance1 === instance2); // true -
Observador (Observer): Para implementar a relação "um-para-muitos", onde ao alterar o estado de um objeto (emissor), todos os objetos dependentes (assinantes) são automaticamente notificados. Usado em sistemas de notificações, interfaces reativas.
// Exemplo de uso do observador class Observable { 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 { update(data) { console.log("Recebeu atualização:", data); } } const observable = new Observable(); const observer1 = new Observer(); const observer2 = new Observer(); observable.subscribe(observer1); observable.subscribe(observer2); observable.notify("Novos dados disponíveis!"); -
Estratégia (Strategy): Para definir uma família de algoritmos, encapsulá-los e torná-los intercambiáveis. Permite que o algoritmo varie independentemente dos clientes que o utilizam. Aplicado em diferentes variantes de processamento de dados ou execução de operações.
// Exemplo de uso da estratégia class PaymentStrategy { pay(amount) { throw new Error("Método não implementado"); } } class CreditCardPayment extends PaymentStrategy { pay(amount) { console.log(`A pagar ${amount} usando cartão de crédito`); } } class PayPalPayment extends PaymentStrategy { pay(amount) { console.log(`A pagar ${amount} usando PayPal`); } } class PaymentContext { setStrategy(strategy) { this.strategy = strategy; } executePayment(amount) { this.strategy.pay(amount); } } const context = new PaymentContext(); context.setStrategy(new CreditCardPayment()); context.executePayment(100); context.setStrategy(new PayPalPayment()); context.executePayment(50); -
Decorador (Decorator): Para adicionar funcionalidades novas a um objeto de forma dinâmica sem alterar a sua estrutura. Envolve o objeto existente, fornecendo a mesma interface que o objeto envolvido, mas com funcionalidades adicionais. Útil para logging, validação, caching.
// Exemplo de uso do decorador class Component { operation() { return "Componente Básico"; } } class Decorator { constructor(component) { this.component = component; } operation() { return this.component.operation(); } } class ConcreteDecoratorA extends Decorator { operation() { return `DecoradorConcretoA(${super.operation()})`; } } class ConcreteDecoratorB extends Decorator { operation() { return `DecoradorConcretoB(${super.operation()})`; } } const simple = new Component(); console.log(simple.operation()); const decoratorA = new ConcreteDecoratorA(simple); console.log(decoratorA.operation()); const decoratorB = new ConcreteDecoratorB(decoratorA); console.log(decoratorB.operation()); -
Módulo (Module): Embora o sistema de módulos do Node.js seja incorporado (CommonJS, ES Modules), o padrão Module pattern em JavaScript (antes do surgimento de módulos nativos) era usado para criar membros privados e uma interface pública. É a base para construir código encapsulado.
Estes padrões ajudaram-me a criar um código mais estruturado, escalável e de fácil manutenção.