GoF aplicado ao mundo real
Os 5 padrões de projeto mais usados no desenvolvimento moderno, com exemplos reais em TypeScript, comparativos antes/depois e guia de quando usar cada um.
Padrões de projeto são soluções reutilizáveis para problemas recorrentes no desenvolvimento de software. Não são bibliotecas — são vocabulário e estrutura.
Comunicação
Equipes que conhecem os padrões falam a mesma língua: 'use o Strategy aqui' é mais preciso do que 'crie uma abstração'.
Manutenibilidade
Código que segue padrões conhecidos é mais fácil de estender sem quebrar o que já existe.
Entrevistas
Conhecer os padrões GoF é esperado em entrevistas sênior. Saber quando NÃO usar também.
Notifique múltiplos objetos quando um estado muda.
Define uma dependência um-para-muitos entre objetos. Quando um objeto muda de estado, todos os seus dependentes são notificados automaticamente.
No mundo real: Event listeners do DOM, useState + useEffect no React, Redux, Zustand.
// ❌ Antes: acoplamento direto entre componentesfunction UserProfile() {const handleUpdate = () => {// Tem que chamar cada componente manualmenteupdateHeader(user);updateSidebar(user);updateNotifications(user);updateAnalytics(user);};}
Troque algoritmos em tempo de execução.
Define uma família de algoritmos, encapsula cada um e os torna intercambiáveis. O cliente pode escolher qual algoritmo usar sem alterar o código que o utiliza.
No mundo real: Ordenação configurável, diferentes formas de pagamento, validadores intercambiáveis.
// ❌ Antes: switch/case que cresce infinitamentefunction sortData(data: Item[], method: string) {if (method === "name") {return data.sort((a, b) => a.name.localeCompare(b.name));} else if (method === "price") {return data.sort((a, b) => a.price - b.price);} else if (method === "date") {return data.sort((a, b) => a.date.getTime() - b.date.getTime());}// Cada novo critério = modificar esta funçãoreturn data;}
Delegue a criação de objetos para subclasses.
Define uma interface para criar objetos, mas deixa as subclasses decidirem qual classe instanciar. O Factory Method adia a instanciação para as subclasses.
No mundo real: React.createElement, document.createElement, criação de conexões de banco.
// ❌ Antes: lógica de criação espalhadafunction createButton(type: string) {if (type === "primary") {const btn = document.createElement("button");btn.className = "btn-primary";btn.style.backgroundColor = "#007bff";return btn;} else if (type === "danger") {const btn = document.createElement("button");btn.className = "btn-danger";btn.style.backgroundColor = "#dc3545";return btn;}// Duplicação em cada lugar que precisa criar botões}
Adicione responsabilidades a objetos dinamicamente.
Anexa responsabilidades adicionais a um objeto dinamicamente. Decoradores fornecem uma alternativa flexível à herança para estender funcionalidade.
No mundo real: HOCs no React, middleware no Express/Next.js, decorators do TypeScript.
// ❌ Antes: herança para cada combinaçãoclass Logger { log(msg: string) { console.log(msg); } }class TimestampLogger extends Logger { /* ... */ }class JsonLogger extends Logger { /* ... */ }class TimestampJsonLogger extends Logger { /* ... */ }// N funcionalidades = 2^N subclasses possíveis
Encapsule ações como objetos.
Encapsula uma requisição como um objeto, permitindo parametrizar clientes com diferentes requisições, enfileirar ou registrar requisições, e implementar operações desfazíveis.
No mundo real: Undo/redo em editores, filas de tarefas, transações de banco de dados.
// ❌ Antes: ações diretas sem históricofunction TextEditor() {const [text, setText] = useState("");const bold = () => setText(t => `**${t}**`);const italic = () => setText(t => `_${t}_`);// Impossível desfazer — não há histórico}
Um dos erros mais comuns é aplicar padrões desnecessariamente. Saiba identificar o momento certo.
Observer
Use quando...
Não use quando...
Strategy
Use quando...
Não use quando...
Factory
Use quando...
Não use quando...
Decorator
Use quando...
Não use quando...
Command
Use quando...
Não use quando...
Padrões são ferramentas, não regras. Use quando simplificam o design, não para impressionar.