Pular para o conteúdo

Padrões Comportamentais

Enquanto os Padrões Criacionais cuidam da instanciação e os Padrões Estruturais da composição, os comportamentais descrevem como objetos interagem e distribuem responsabilidades. Muitos deles substituem herança rígida por composição e delegação, transformando fluxo de controle estático (condicionais, herança) em relações dinâmicas entre objetos.

São 11 padrões no catálogo original. Cinco deles têm nota própria neste vault e estão destacados abaixo.

Encadeia objetos receptores para que uma requisição percorra a cadeia até que algum deles a trate. Desacopla o emissor do receptor concreto. Quando usar: múltiplos handlers possíveis, ordem/composição dinâmica, pipelines de validação ou filtros. Ver Chain of Responsibility.

Encapsula uma requisição como objeto, permitindo parametrizar clientes, enfileirar, registrar em log e desfazer operações. Quando usar: undo/redo, filas de tarefas, macros, transações. Ver Command.

Define uma representação gramatical de uma linguagem e um interpretador que avalia sentenças dessa gramática. Quando usar: DSLs simples, expressões (regras, filtros, matemática) com gramática estável e pequena. Raro em aplicações de negócio; costuma ser substituído por parsers dedicados.

Provê acesso sequencial aos elementos de uma coleção sem expor sua representação interna. Quando usar: percorrer estruturas heterogêneas de forma uniforme. Em Java, já é onipresente via Iterator/Iterable e o for-each.

Centraliza a comunicação entre um conjunto de objetos num objeto mediador, substituindo relações N-para-N por relações N-para-1. Quando usar: muitos objetos com interdependência caótica (ex.: componentes de UI). Ver Mediator.

Captura e externaliza o estado interno de um objeto sem violar seu encapsulamento, permitindo restaurá-lo depois. Quando usar: snapshots, checkpoints, undo baseado em estado (complementa Command).

Define dependência um-para-muitos: quando um objeto muda de estado, todos os dependentes são notificados automaticamente. Quando usar: publish-subscribe, reatividade, listeners, base conceitual de Domain Events. Ver Observer.

Permite que um objeto altere seu comportamento quando seu estado interno muda; o objeto parece mudar de classe. Quando usar: máquinas de estado, comportamento condicionado por estado. É primo estrutural do Strategy: mesma estrutura (delegação a um objeto de comportamento), mas com intenção diferente — o State conhece e controla suas transições; a Strategy é escolhida de fora e ignora as demais.

Encapsula uma família de algoritmos intercambiáveis, tornando-os independentes do cliente que os usa. Quando usar: variações de algoritmo selecionáveis, eliminar condicionais de seleção. Ver Strategy.

Define o esqueleto de um algoritmo numa operação, delegando passos específicos às subclasses. Quando usar: algoritmos com estrutura fixa e variação pontual de passos. É a versão baseada em herança; o Strategy é a alternativa por composição.

Representa uma operação a ser executada sobre os elementos de uma estrutura de objetos, permitindo adicionar novas operações sem alterar as classes dos elementos. Quando usar: hierarquias estáveis com muitas operações distintas (compiladores, AST). Sacrifica a facilidade de adicionar novos tipos em troca da facilidade de adicionar novas operações.

  • Herança vs. composição: Template Method usa herança; Strategy e State usam composição. Prefira composição quando quiser variação em runtime.
  • Acoplamento de comunicação: Observer descentraliza (emissor não conhece receptores); Mediator centraliza (todos conhecem o mediador).
  • Onde vive o algoritmo: Strategy o coloca em objetos externos; Interpreter numa gramática; Visitor num objeto de operação separado dos dados.
  • Aplicar um comportamental onde uma condicional simples bastava. Nem todo if merece virar objeto. Padrões comportamentais custam indireção; use-os quando há variação real ou prevista.
  • Confundir Strategy e State por terem a mesma UML. A diferença é semântica: intenção e responsabilidade pela transição.
  • Transformar Mediator em God Object ao concentrar regras demais nele.
  • Observers com efeitos colaterais em cascata que criam dependências implícitas difíceis de rastrear.

1. Qual é o foco dos padrões comportamentais em contraste com criacionais e estruturais?

Resposta

A atribuição de responsabilidades e os padrões de comunicação entre objetos, ou seja, como o comportamento é distribuído e como objetos interagem em runtime — não como são criados (criacionais) nem como são compostos estruturalmente (estruturais).

2. Strategy e State têm a mesma estrutura. Como distingui-los?

Resposta

Pela intenção. Strategy encapsula algoritmos intercambiáveis escolhidos de fora; cada estratégia ignora as outras. State encapsula comportamento dependente de estado, e os estados normalmente conhecem e disparam as transições entre si. A UML é idêntica; a semântica e a responsabilidade pela troca diferem.

3. Quando preferir Template Method a Strategy?

Resposta

Template Method (herança) cabe quando o esqueleto do algoritmo é fixo e apenas alguns passos variam, com hierarquia estável. Strategy (composição) é melhor para variação em runtime, quando se quer trocar o algoritmo inteiro sem herança e favorecendo baixo acoplamento e testabilidade.

4. Qual a diferença de acoplamento entre Observer e Mediator?

Resposta

Observer descentraliza: o emissor (subject) notifica observers sem conhecê-los concretamente, relação um-para-muitos. Mediator centraliza: transforma comunicação N-para-N num hub, reduzindo o acoplamento direto entre os colegas, mas concentrando complexidade — com risco de virar God Object.