Menu
Coddy logo textTech

Padrão Observer

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 68 de 87.

O Observer Pattern é um padrão de projeto comportamental que estabelece uma relação de um-para-muitos entre objetos. Quando um objeto (o sujeito) muda de estado, todos os seus dependentes (os observadores) são notificados e atualizados automaticamente. Pense nisso como uma assinatura de newsletter — os assinantes recebem atualizações sempre que um novo conteúdo é publicado.

O padrão envolve dois componentes principais: um sujeito que mantém uma lista de observadores e os notifica sobre mudanças, e observadores que definem um método de atualização para responder a notificações:

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class NewsPublisher {
    private List<Observer> subscribers = new ArrayList<>();
    
    public void subscribe(Observer observer) {
        subscribers.add(observer);
    }
    
    public void unsubscribe(Observer observer) {
        subscribers.remove(observer);
    }
    
    public void publish(String news) {
        for (Observer subscriber : subscribers) {
            subscriber.update(news);
        }
    }
}

class EmailSubscriber implements Observer {
    private String email;
    
    public EmailSubscriber(String email) {
        this.email = email;
    }
    
    public void update(String message) {
        System.out.println("Email to " + email + ": " + message);
    }
}

Quando o publicador lança notícias, todos os assinantes são notificados automaticamente:

NewsPublisher publisher = new NewsPublisher();
publisher.subscribe(new EmailSubscriber("alice@mail.com"));
publisher.subscribe(new EmailSubscriber("bob@mail.com"));

publisher.publish("Breaking news!");
// Saída:
// E-mail para alice@mail.com: Breaking news!
// E-mail para bob@mail.com: Breaking news!

O Padrão Observer promove o baixo acoplamento — o sujeito não precisa conhecer as classes concretas de seus observadores, apenas que eles implementam a interface Observer. Isso torna fácil adicionar novos tipos de observadores sem modificar o sujeito.

challenge icon

Desafio

Fácil

Vamos construir um sistema de alerta de preços de ações usando o Observer Pattern! Você criará um sistema onde um ticker de ações notifica múltiplos investidores sempre que o preço da ação muda, permitindo que cada investidor reaja às atualizações de preço à sua maneira.

Você organizará seu código em quatro arquivos:

  • Observer.java: Defina a interface Observer que todos os investidores implementarão. Ela deve declarar um único método update(String stockName, double price) que os observadores usam para receber notificações sobre mudanças de preço.
  • StockTicker.java: Crie a classe sujeito que mantém uma lista de observadores e os notifica sobre mudanças de preço. Seu StockTicker deve ter:

    Um campo String privado para o nome da ação (definido via construtor).

    Um campo double privado para o preço atual (inicialmente 0).

    Uma lista privada para armazenar os observadores inscritos.

    Um método subscribe(Observer observer) que adiciona um observador à lista.

    Um método unsubscribe(Observer observer) que remove um observador da lista.

    Um método setPrice(double price) que atualiza o preço e então notifica todos os observadores chamando seu método update com o nome da ação e o novo preço.

  • Investors.java: Crie dois tipos diferentes de investidores que implementam a interface Observer:

    DayTrader - possui um campo de nome privado definido via construtor. Quando atualizado, imprime [name] received alert: [stockName] is now $[price] - Making quick trade!

    LongTermInvestor - possui um campo de nome privado definido via construtor. Quando atualizado, imprime [name] received alert: [stockName] is now $[price] - Holding steady.

    Formate o preço com duas casas decimais.

  • Main.java: Reúna seu sistema de observadores! Você receberá três entradas: o nome da ação (String), a primeira atualização de preço (double) e a segunda atualização de preço (double).

    Crie um StockTicker com o nome da ação fornecido. Crie um DayTrader chamado "Alice" e um LongTermInvestor chamado "Bob", e inscreva ambos no ticker.

    Defina o preço para o primeiro valor de entrada (todos os observadores são notificados). Em seguida, cancele a inscrição de Alice. Por fim, defina o preço para o segundo valor de entrada (apenas Bob deve ser notificado desta vez).

Você receberá três entradas em ordem: nome da ação (String), primeiro preço (double), segundo preço (double).

Este desafio demonstra o poder do Observer Pattern: o StockTicker não sabe nada sobre os tipos específicos de investidores — ele apenas sabe que eles implementam Observer. Quando você cancela a inscrição de Alice, ela para de receber atualizações enquanto Bob continua sendo notificado. Este acoplamento fraco facilita a adição de novos tipos de investidores sem alterar o ticker!

Folha de consulta

O Observer Pattern (Padrão Observador) é um padrão de projeto comportamental que estabelece uma relação de um-para-muitos entre objetos. Quando um objeto (o subject) muda de estado, todos os seus dependentes (os observers) são notificados e atualizados automaticamente.

O padrão envolve dois componentes principais:

  • Subject: Mantém uma lista de observadores e os notifica sobre mudanças
  • Observers: Definem um método de atualização para responder a notificações

Estrutura básica:

import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class Subject {
    private List<Observer> observers = new ArrayList<>();
    
    public void subscribe(Observer observer) {
        observers.add(observer);
    }
    
    public void unsubscribe(Observer observer) {
        observers.remove(observer);
    }
    
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

class ConcreteObserver implements Observer {
    public void update(String message) {
        // Reagir à notificação
    }
}

Exemplo de uso:

Subject subject = new Subject();
subject.subscribe(new ConcreteObserver());
subject.notifyObservers("State changed!");
// Todos os observadores inscritos recebem a atualização

O Observer Pattern promove o acoplamento fraco (loose coupling)—o subject não precisa conhecer as classes concretas de seus observers, apenas que eles implementam a interface Observer. Isso facilita a adição de novos tipos de observadores sem modificar o subject.

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Ler as entradas
        String stockName = scanner.nextLine();
        double firstPrice = scanner.nextDouble();
        double secondPrice = scanner.nextDouble();
        
        // TODO: Criar um StockTicker com o nome da ação fornecido
        
        // TODO: Criar um DayTrader chamado "Alice"
        
        // TODO: Criar um LongTermInvestor chamado "Bob"
        
        // TODO: Inscrever tanto Alice quanto Bob no ticker
        
        // TODO: Definir o preço como firstPrice (ambos os observadores são notificados)
        
        // TODO: Cancelar a inscrição de Alice
        
        // TODO: Definir o preço como secondPrice (apenas Bob é notificado)
        
        scanner.close();
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos