Resumo de estudo · Padrões de Projeto

Observer.

Padrão comportamental do catálogo GoF. Define uma dependência um-para-muitos entre objetos: quando um muda de estado, todos os seus dependentes são notificados e atualizados automaticamente.

Disciplina
Engenharia de Software · cap. 6, Padrões de Projeto
Autor
Nicolas Garcia · Ciência da Computação, 5º período
Data
Outubro de 2026

01Em uma frase

O Observer permite que um objeto anuncie que algo mudou e que qualquer número de outros objetos reaja, sem que o emissor saiba quem são, quantos são ou o que fazem.

Nomes alternativos: Publish–Subscribe, Dependents, Listener. O emissor é chamado de Subject ou Observable; o receptor, de Observer ou Listener.

02O problema que resolve

Quando a mudança de estado de um objeto precisa disparar reações em vários outros, aparecem duas saídas ingênuas, e as duas envelhecem mal:

O Observer inverte a direção do conhecimento: o interessado se registra, e o emissor passa a conhecer apenas uma interface.

03Participantes

PapelResponsabilidadeOperações
SubjectMantém a lista de observadores e oferece o registro.inscrever() cancelar() notificar()
ObserverInterface de retorno que todo interessado implementa.atualizar()
ConcreteSubjectGuarda o estado real e chama notificar() quando ele muda.getEstado() setEstado()
ConcreteObserverImplementa a reação concreta ao aviso.atualizar()

04Como funciona

  1. Os observadores se registram no Subject com inscrever().
  2. Algo altera o estado do Subject: setEstado().
  3. O Subject chama notificar(), que percorre a lista.
  4. Para cada observador registrado, chama atualizar().
  5. Cada observador reage, lendo o estado do Subject (pull) ou usando o dado recebido (push).
  6. Quem não quer mais ser avisado chama cancelar(). É o passo mais esquecido e a origem do vazamento de memória.

Push, pull e híbrido

ModeloAssinaturaVantagemCusto
Pushatualizar(status, valor)Direto; o observador não consulta nada.O Subject presume o que cada um precisa; a assinatura cresce.
Pullatualizar(subject)Cada um busca só o que interessa; o Subject fica genérico.Uma chamada extra; o observador conhece a API do Subject.
Híbridoatualizar(evento)Objeto de evento com o essencial e a referência. É o mais usado.Mais uma classe para manter.

05Implementação de referência

// contrato public interface Observador { void atualizar(Pedido p); } // subject public class Pedido { private final List<Observador> obs = new ArrayList<>(); private Status status; public void inscrever(Observador o) { obs.add(o); } public void cancelar(Observador o) { obs.remove(o); } public void setStatus(Status novo) { this.status = novo; // estado consistente ANTES de avisar notificar(); } private void notificar() { // cópia defensiva: um observador pode cancelar durante o laço for (Observador o : List.copyOf(obs)) o.atualizar(this); } public Status getStatus() { return status; } } // observadores concretos: não se conhecem entre si class EnviarEmail implements Observador { public void atualizar(Pedido p) { ... } } class BaixarEstoque implements Observador { public void atualizar(Pedido p) { ... } } // uso Pedido pedido = new Pedido(); pedido.inscrever(new EnviarEmail()); pedido.inscrever(new BaixarEstoque()); pedido.setStatus(Status.PAGO); // os dois reagem

O teste do padrão: para acrescentar a emissão de nota fiscal, cria-se uma classe nova e chama-se inscrever. A classe Pedido não muda. É o Princípio Aberto/Fechado aplicado.

06Onde o padrão aparece

TecnologiaComo aparece
DOM / JavaScriptelement.addEventListener('click', fn): o elemento é o Subject, a função é o Observer.
React / VueEstado reativo: o componente observa o estado e renderiza de novo quando ele muda.
Redux / Vuex / Piniastore.subscribe(listener): a interface observa a store.
Java SEActionListener, PropertyChangeListener, Flow.Subscriber. As antigas Observable/Observer foram depreciadas no Java 9.
SpringApplicationEventPublisher e @EventListener.
DjangoSignals: post_save, pre_delete e receptores conectados.
RxJSObservable.subscribe(): Observer estendido com fluxo, operadores e cancelamento.
WebhooksObserver sobre HTTP: você registra uma URL e o serviço a chama quando o evento ocorre.
Kafka / RabbitMQ / SNSPub/Sub distribuído: mesma intenção, com intermediário e entrega assíncrona.
MVCA View observa o Model. É o uso original do padrão, no Smalltalk-80.

07Vantagens

  • Baixo acoplamento: o Subject depende só da interface Observer.
  • Aberto/Fechado: novos observadores sem alterar o Subject.
  • Vínculo dinâmico: inscrição e cancelamento em execução.
  • Broadcast: um evento, N reações, sem o emissor saber quantas.
  • Responsabilidade única: cada reação isolada e testável sozinha.
  • Reuso independente de Subject e de Observer.

08Desvantagens

  • Vazamento de memória: o lapsed listener nunca é coletado.
  • Ordem indefinida de notificação.
  • Cascatas e ciclos quando um observador altera outro Subject.
  • Depuração difícil: o fluxo deixa de ser explícito na pilha.
  • Bloqueio e falha em cadeia na versão síncrona.
  • Modificação concorrente da lista durante a notificação.

09Observer × Publish/Subscribe

CritérioObserver (GoF)Pub/Sub (mensageria)
ConhecimentoO Subject mantém a lista de observadores.Publicador e assinante não se conhecem; há um broker.
AcoplamentoBaixo, com referência direta em memória.Quase nulo, só o nome do tópico ou canal.
EscopoDentro de um processo.Entre processos, serviços e máquinas.
ExecuçãoGeralmente síncrona.Assíncrona, com fila, retentativa e persistência.
ExemplosaddEventListener, Swing, Spring Events.Kafka, RabbitMQ, SNS, webhooks.

10Quando usar e quando evitar

Use quando

  • Uma mudança em um objeto exige mudanças em outros que não são conhecidos de antemão.
  • O conjunto de interessados varia em tempo de execução.
  • Você quer separar o que aconteceu de o que fazer a respeito.
  • O mesmo evento alimenta interface, log, métricas e integrações ao mesmo tempo.

Evite quando

  • Existe um único dependente fixo: a chamada direta é mais legível.
  • A ordem das reações é requisito de negócio.
  • É preciso garantia de entrega ou reprocessamento: use fila.
  • As reações devem ser transacionais junto com a mudança de estado.

11Padrões relacionados

12Checklist de implementação

  1. Separe o que muda (estado) de quem reage (comportamentos independentes).
  2. Declare a interface Observer com um único método de atualização.
  3. No Subject, mantenha a coleção de observadores e os métodos de registro.
  4. Chame notificar() depois de o estado estar consistente.
  5. Percorra uma cópia da lista, para suportar cancelamento durante a notificação.
  6. Trate a exceção de cada observador isoladamente, para que um não derrube os outros.
  7. Garanta o cancelar() no ciclo de vida do observador, ou use referências fracas.
  8. Se precisar de ordem, assincronia ou entrega garantida, passe para fila ou mensageria.

13Perguntas prováveis da banca

Observer é o mesmo que Pub/Sub?

Mesma intenção, escalas diferentes. No Observer o Subject conhece a lista e a chamada costuma ser síncrona, dentro do processo. No Pub/Sub há um broker no meio, e publicador e assinante não se conhecem.

Por que Observable e Observer do Java foram depreciadas?

Não eram serializáveis, não garantiam ordem nem suportavam concorrência, e Observable era uma classe, o que obrigava herança e gastava a única superclasse disponível. Desde o Java 9 recomenda-se PropertyChangeListener ou a API java.util.concurrent.Flow.

Qual princípio SOLID ele materializa?

Principalmente o Aberto/Fechado: estende-se o comportamento acrescentando observadores, sem modificar o Subject. Também a Responsabilidade Única e a Inversão de Dependência, já que o Subject depende de uma abstração.

Como evitar o vazamento de memória?

Garantindo o cancelar() no fim do ciclo de vida do observador (em um finally, dispose ou onDestroy), ou guardando os observadores por referência fraca (WeakReference).

E se um observador lançar exceção?

Na implementação ingênua ele interrompe o laço e os seguintes não são notificados. A correção é capturar a exceção de cada observador dentro do notificar(), registrar o erro e continuar.

Observer é síncrono ou assíncrono?

O padrão não define. A implementação clássica do GoF é síncrona: notificar() só retorna quando todos reagiram. Versões assíncronas despacham para uma fila ou um pool de threads.

14Referências