Menu
Coddy logo textTech

Padrão Observer

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 92 de 110.

O padrão Observer estabelece uma relação de um-para-muitos entre objetos: quando um objeto (o sujeito) muda de estado, todos os seus dependentes (observadores) são notificados automaticamente. Isso é perfeito para cenários como atualizações de UI, sistemas de eventos ou qualquer situação em que várias partes da sua aplicação precisem reagir a mudanças.

O padrão envolve dois papéis principais: um Subject que mantém uma lista de observadores e os notifica sobre mudanças, e Observers que se registram e respondem a atualizações:

abstract class Observer {
  void update(String message);
}

class NewsAgency {
  final List<Observer> _observers = [];
  String _latestNews = '';

  void subscribe(Observer observer) {
    _observers.add(observer);
  }

  void unsubscribe(Observer observer) {
    _observers.remove(observer);
  }

  void publishNews(String news) {
    _latestNews = news;
    for (var observer in _observers) {
      observer.update(_latestNews);
    }
  }
}

class NewsChannel implements Observer {
  final String name;
  NewsChannel(this.name);

  @override
  void update(String message) {
    print('$name received: $message');
  }
}

void main() {
  var agency = NewsAgency();
  var cnn = NewsChannel('CNN');
  var bbc = NewsChannel('BBC');

  agency.subscribe(cnn);
  agency.subscribe(bbc);

  agency.publishNews('Breaking news!');
  // CNN recebeu: Breaking news!
  // BBC recebeu: Breaking news!
}

Quando publishNews é chamado, a agência itera por todos os observadores inscritos e chama o método update deles. Os observadores podem se inscrever ou cancelar a inscrição a qualquer momento, tornando o sistema flexível e fracamente acoplado - o sujeito não precisa conhecer os tipos específicos de seus observadores.

challenge icon

Desafio

Fácil

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

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

  • stock_system.dart: Crie seu sistema observer aqui:
    • Uma classe abstrata Investor com um método void onPriceChange(String stockName, double price)
    • Uma classe DayTrader que implementa Investor. Ela possui um campo name e seu método onPriceChange imprime: [name] sees [stockName] at $[price] - Making quick trade!
    • Uma classe LongTermInvestor que implementa Investor. Ela possui um campo name e seu método onPriceChange imprime: [name] notes [stockName] at $[price] - Holding steady.
    • Uma classe StockTicker (o sujeito) com:
      • Um campo String stockName
      • Uma lista privada para armazenar os investidores inscritos
      • Um método subscribe(Investor investor) para adicionar um investidor
      • Um método unsubscribe(Investor investor) para remover um investidor
      • Um método updatePrice(double newPrice) que notifica todos os investidores inscritos sobre o novo preço
  • main.dart: Importe seu sistema de ações e demonstre o padrão Observer em ação:
    • Crie um StockTicker para uma ação chamada DART
    • Crie uma DayTrader chamada Alice e um LongTermInvestor chamado Bob
    • Inscreva ambos os investidores no ticker
    • Atualize o preço para 150.50 (ambos os investidores devem ser notificados)
    • Imprima uma linha vazia
    • Remova a inscrição de Alice do ticker
    • Atualize o preço para 155.75 (apenas Bob deve ser notificado agora)

Isso demonstra como o padrão Observer cria um sistema fracamente acoplado - o StockTicker não precisa saber se está notificando day traders ou investidores de longo prazo, ele apenas chama onPriceChange em quem estiver inscrito!

Saída esperada:

Alice sees DART at $150.5 - Making quick trade!
Bob notes DART at $150.5 - Holding steady.

Bob notes DART at $155.75 - Holding steady.

Folha de consulta

O padrão Observer estabelece uma relação de um para muitos onde um sujeito (subject) notifica todos os seus observadores quando seu estado muda.

O padrão possui dois papéis principais:

  • Subject: Mantém uma lista de observadores e os notifica sobre mudanças
  • Observer: Registra-se no subject e responde às atualizações

Implementação básica:

abstract class Observer {
  void update(String message);
}

class Subject {
  final List<Observer> _observers = [];

  void subscribe(Observer observer) {
    _observers.add(observer);
  }

  void unsubscribe(Observer observer) {
    _observers.remove(observer);
  }

  void notifyObservers(String data) {
    for (var observer in _observers) {
      observer.update(data);
    }
  }
}

class ConcreteObserver implements Observer {
  final String name;
  ConcreteObserver(this.name);

  @override
  void update(String message) {
    print('$name received: $message');
  }
}

Principais benefícios:

  • Acoplamento fraco entre o subject e os observadores
  • Observadores podem se inscrever/cancelar a inscrição dinamicamente
  • O subject não precisa conhecer os tipos específicos de observadores

Experimente você mesmo

import 'stock_system.dart';

void main() {
  // TODO: Create a StockTicker for a stock named 'DART'
  
  // TODO: Create a DayTrader named 'Alice'
  
  // TODO: Create a LongTermInvestor named 'Bob'
  
  // TODO: Subscribe both investors to the ticker
  
  // TODO: Update the price to 150.50 (both investors should be notified)
  
  // TODO: Print an empty line
  
  // TODO: Unsubscribe Alice from the ticker
  
  // TODO: Update the price to 155.75 (only Bob should be notified now)
}
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