Padrões de Projeto em TypeScript: do Simples ao Complexo
Padrões de projeto (design patterns) são soluções testadas pelo tempo para problemas típicos no desenvolvimento de software. No contexto do TypeScript, que adiciona ao JavaScript tipagem estática e recursos de POO, os padrões se tornam especialmente eficazes. O TypeScript permite implementar abstrações, interfaces e polimorfismo em um novo nível, tornando o código mais previsível e seguro.
Neste artigo, abordaremos os principais padrões de projeto, sua implementação em TypeScript e exemplos práticos de uso. O material será útil tanto para desenvolvedores iniciantes quanto para profissionais experientes que desejam sistematizar seus conhecimentos.
Padrões Criacionais: Singleton e Factory Method
Os padrões criacionais são responsáveis pela criação de objetos, ocultando a lógica de instanciação. Vamos analisar dois dos mais populares: Singleton e Factory Method.
Singleton
O Singleton garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a ela. Em TypeScript, a implementação se torna especialmente elegante graças a membros estáticos e construtores privados.
class DatabaseConnection { private static instance: DatabaseConnection; private connectionString: string;
private constructor(connectionString: string) { this.connectionString = connectionString; console.log(`Conexão criada com: ${connectionString}`); }
static getInstance(connectionString: string): DatabaseConnection { if (!DatabaseConnection.instance) { DatabaseConnection.instance = new DatabaseConnection(connectionString); } return DatabaseConnection.instance; }
query(sql: string): void { console.log(`Executando consulta: ${sql} em ${this.connectionString}`); }}
// Usoconst db1 = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');const db2 = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');console.log(db1 === db2); // true - mesmo objetoEste padrão é ideal para gerenciar recursos: pools de conexão, logging, cache. No entanto, tenha cuidado — o Singleton pode dificultar os testes devido ao estado global.
Factory Method (Método Fábrica)
O Factory Method define uma interface para criar um objeto, mas permite que as subclasses alterem o tipo do objeto criado. Em TypeScript, isso é implementado por meio de classes abstratas ou interfaces.
interface Notification { send(message: string): void;}
class EmailNotification implements Notification { send(message: string): void { console.log(`Enviando email: ${message}`); }}
class SMSNotification implements Notification { send(message: string): void { console.log(`Enviando SMS: ${message}`); }}
abstract class NotificationFactory { abstract createNotification(): Notification;
notify(message: string): void { const notification = this.createNotification(); notification.send(message); }}
class EmailFactory extends NotificationFactory { createNotification(): Notification { return new EmailNotification(); }}
class SMSFactory extends NotificationFactory { createNotification(): Notification { return new SMSNotification(); }}
// Usoconst factory: NotificationFactory = new EmailFactory();factory.notify('Seu pedido foi confirmado!');O Factory Method ajuda a respeitar o princípio aberto/fechado (OCP) — você pode adicionar novos tipos de notificação sem alterar o código existente.
Padrões Estruturais: Adapter e Decorator
Os padrões estruturais ajudam a organizar as relações entre objetos e classes, tornando o sistema mais flexível e extensível.