Entendendo GoF (Gang of Four) e por que ainda são tão importantes

Se você trabalha com desenvolvimento de software há algum tempo, provavelmente já ouviu falar dos famosos Design Patterns — e principalmente do termo GoF (Gang of Four).

Mas… por que isso ainda importa tanto hoje, em um mundo com microservices, cloud, IA e frameworks cada vez mais abstraídos?

A resposta é simples: problemas clássicos ainda existem — e soluções bem estruturadas continuam sendo valiosas.

📚 O que é GoF?

O termo GoF (Gang of Four) se refere ao livro clássico:

👉 “Design Patterns: Elements of Reusable Object-Oriented Software”

Escrito por quatro autores (Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides), esse livro definiu 23 padrões de projeto que até hoje são referência no desenvolvimento orientado a objetos.

Esses padrões não são código pronto, mas sim formas testadas de resolver problemas recorrentes de design.

🚀 Por que isso ainda é relevante?

Mesmo com frameworks modernos como Spring Boot, Angular, ou arquiteturas baseadas em eventos e cloud:

  • Você ainda precisa organizar código
  • Precisa garantir baixo acoplamento
  • Precisa facilitar manutenção e evolução
  • E principalmente: precisa comunicar bem as soluções com o time

👉 E é aí que os padrões brilham.

Eles funcionam como uma linguagem universal entre desenvolvedores.

Quando você fala:

“Aqui usei Strategy”

Outro dev experiente já entende a ideia — sem precisar ler toda a implementação.

🧩 Categorias de padrões GoF

Os padrões do GoF são divididos em três grandes grupos:

  • Criacionais → criação de objetos
  • Estruturais → organização entre classes
  • Comportamentais → comunicação e comportamento entre objetos

👉 E é exatamente aqui que vamos começar.

🎯 O foco deste post: padrões comportamentais

Neste primeiro post, vamos explorar três padrões comportamentais extremamente úteis no dia a dia:

🔁 Strategy

Permite trocar algoritmos de forma dinâmica.

👉 Ideal quando você tem várias formas de executar uma mesma operação.

Exemplo clássico:

  • Diferentes formas de cálculo (frete, desconto, imposto)

Abaixo um exemplo utilizando o spring boot, note que dessa forma basta que eu crie novas classes e elas são incluídas na minha lista de forma dinâmica e com isso eu não quebro o Open Closed do SOLID e deixo meu código muito mais organizado

public interface MissaoStrategy {

void execute(MissaoDto missaoDto);
Boolean apply(MissaoDto missaoDto);

}
public class MissaoPsnStrategy implements MissaoStrategy{
    @Override
    public void execute(MissaoDto missaoDto) {

    }

    @Override
    public Boolean apply(MissaoDto missaoDto) {
        return missaoDto.missao().equalsIgnoreCase("psn")
                && missaoDto.type().equalsIgnoreCase("valor");
    }
}
public class MissaoNetflixStrategy implements MissaoStrategy{
    @Override
    public void execute(MissaoDto missaoDto) {

    }

    @Override
    public Boolean apply(MissaoDto missaoDto) {
        return missaoDto.missao().equalsIgnoreCase("netflix")
                && missaoDto.type().equalsIgnoreCase("valor");
    }
}
@Service
@RequiredArgsConstructor
@Slf4j
public class StrategyServiceApp {

    private final List<MissaoStrategy> missaoStrategies;

    public void pontuar(MissaoDto missaoDto){
        var missao = missaoStrategies.stream()
                .filter(missaoStrategy -> missaoStrategy.apply(missaoDto))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Missão selecionada é inválida."));
        log.debug("missao selecionada: {}", missao.getClass().getSimpleName());
        missao.execute(missaoDto);
    }

}

👀 Observer

Define um mecanismo de notificação entre objetos.

👉 Muito usado em sistemas orientados a eventos.

Exemplo:

  • Um serviço publica um evento e vários consumidores reagem a ele

Abaixo um exemplo utilizando o spring boot, note que dessa forma basta que eu crie novas classes e elas são notificadas de forma que uma não interfere na outra mesmo com regras totalmente diferentes

@Service
@RequiredArgsConstructor
public class ObserverServiceApp {

    private final ApplicationEventPublisher eventPublisher;

    void notificarMissaoConcluida(Evento evento){
        eventPublisher.publishEvent(evento);
    }

}
@Service
@RequiredArgsConstructor
@Slf4j
public class EventoNotificarFornecedorAsdf {

    @EventListener
    void handle(Evento evento){
        log.debug("Notificando fornecedor Asdf: {}", evento);
    }
}
@Service
@RequiredArgsConstructor
@Slf4j
public class EventoNotificarFornecedorXpto {

    @EventListener
    void handle(Evento evento){
        log.debug("Notificando fornecedor Xpto: {}", evento);
    }
}

🔗 Chain of Responsibility

Permite processar uma requisição passando por uma cadeia de handlers.

👉 Cada etapa decide se trata ou passa adiante.

Exemplo:

  • Validações em pipeline
  • Filtros de autenticação/autorização

💡 Por que começar pelos comportamentais?

Porque eles estão em todo lugar hoje:

  • Event-driven architecture → Observer
  • Pipelines e middlewares → Chain
  • Estratégias dinâmicas → Strategy

👉 Ou seja: mesmo que você não perceba, já está usando esses padrões.

📌 O que vem nos próximos posts?

Este é só o começo.

Nos próximos posts, vamos aprofundar:

  • 🏗️ Padrões Criacionais (Factory, Builder, Singleton…)
  • 🧱 Padrões Estruturais (Adapter, Facade, Decorator…)

Sempre com exemplos práticos e aplicados ao mundo real (Java, cloud, arquitetura moderna, etc).

🧠 Conclusão

Os padrões GoF não são “velhos” — eles são fundamentais.

Eles ajudam você a:

  • escrever código mais limpo
  • tomar decisões melhores de arquitetura
  • e evoluir sistemas com mais segurança

👉 No fim das contas, não é sobre decorar padrões…
é sobre reconhecer problemas e aplicar boas soluções.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *