Sobre esta trilha
A trilha Design Patterns responde a uma pergunta que aparece em todo projeto que cresceu: "já escrevi isso antes — mas diferente".
Padrões de projeto são soluções nomeadas para problemas recorrentes de design. Eles não são frameworks nem bibliotecas — são vocabulário. Quando você e seu time conhecem os padrões, a conversa muda de "aquela coisa que faz assim" para "aplica um Strategy aí".
O que você vai aprender
- O que diferencia um padrão de uma solução genérica.
- Como Strategy elimina condicionais que crescem junto com o negócio.
- Como Observer desacopla partes que precisam reagir umas às outras.
- Como Factory centraliza a criação de objetos complexos.
- Como Adapter conecta interfaces incompatíveis sem reescrever nada.
- Quando padrões ajudam — e quando atrapalham.
Aulas
Strategy
Substitua condicionais que crescem com o negócio por comportamentos intercambiáveis. O Strategy é o padrão mais útil para sistemas que mudam frequentemente.
Observer
Deixe partes do sistema reagirem a eventos sem que o emissor saiba quem está ouvindo. A base de todo sistema de eventos, notificações e reatividade.
Factory
Centralize a criação de objetos complexos num único lugar. Quando a lógica de instanciação cresce, Factory evita que ela vaze pelo sistema inteiro.
Adapter
Conecte interfaces incompatíveis sem reescrever nenhuma das duas partes. O padrão essencial para integrar APIs externas e bibliotecas de terceiros.
Padrões não são receitas
O erro mais comum ao aprender padrões é aplicá-los porque "parece certo", não porque há um problema real sendo resolvido. Padrões emergem — você os reconhece depois que o problema aparece, não antes.
| Padrão | Problema que resolve | Sinal de que é hora de aplicar |
|---|---|---|
| Strategy | Lógica que varia por tipo ou contexto | if (tipo === "A") ... else if (tipo === "B")... que cresce a cada sprint |
| Observer | Reação a eventos entre partes desacopladas | Chamadas diretas entre módulos que não deveriam se conhecer |
| Factory | Criação complexa espalhada pelo código | new Coisa(dep1, dep2, dep3) repetido em vários lugares |
| Adapter | Integração com interface incompatível | Código de terceiros misturado com lógica de domínio |
Strategy em prática: antes e depois
O exemplo mais didático de como um padrão transforma código real:
function calcularFrete(pedido: Pedido) {
if (pedido.modalidade === "sedex") {
return pedido.peso * 8.5;
} else if (pedido.modalidade === "pac") {
return pedido.peso * 4.2;
} else if (pedido.modalidade === "retirada") {
return 0;
}
// cada nova transportadora = novo else if
}interface FreteStrategy {
calcular(pedido: Pedido): number;
}
const estrategias: Record<string, FreteStrategy> = {
sedex: { calcular: (p) => p.peso * 8.5 },
pac: { calcular: (p) => p.peso * 4.2 },
retirada: { calcular: () => 0 },
};
function calcularFrete(pedido: Pedido) {
return estrategias[pedido.modalidade].calcular(pedido);
}
// nova transportadora = nova entrada no objeto, zero mudança no restoPróximos passos
Depois desta trilha, os caminhos naturais são:
- Arquitetura Backend — como padrões como Repository e Service Layer organizam o lado do servidor.
- Prática — exercícios que combinam padrões com decisões arquiteturais reais.
- Separação de Responsabilidades e Acoplamento — os princípios que justificam a maioria dos padrões vistos aqui.