Menu
Coddy logo textTech

Patrón Observer

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 92 de 110.

El patrón Observer establece una relación de uno a muchos entre objetos: cuando un objeto (el sujeto) cambia de estado, todos sus dependientes (observadores) son notificados automáticamente. Esto es perfecto para escenarios como actualizaciones de la interfaz de usuario (UI), sistemas de eventos o cualquier situación en la que múltiples partes de su aplicación necesiten reaccionar a los cambios.

El patrón involucra dos roles clave: un Subject que mantiene una lista de observadores y les notifica los cambios, y Observers que se registran a sí mismos y responden a las actualizaciones:

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 received: Breaking news!
  // BBC received: Breaking news!
}

Cuando se llama a publishNews, la agencia itera a través de todos los observadores suscritos y llama a su método update. Los observadores pueden suscribirse o cancelar su suscripción en cualquier momento, lo que hace que el sistema sea flexible y esté débilmente acoplado: el sujeto no necesita conocer los tipos específicos de sus observadores.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de alerta de precios de acciones utilizando el patrón Observer! Crearás un sistema donde un marcador de acciones (stock ticker) notifica a múltiples inversores cada vez que el precio cambia, permitiendo que cada inversor reaccione a las actualizaciones del mercado a su manera.

Organizarás tu código en dos archivos:

  • stock_system.dart: Crea tu sistema de observadores aquí:
    • Una clase abstracta Investor con un método void onPriceChange(String stockName, double price)
    • Una clase DayTrader que implementa Investor. Tiene un campo name y su método onPriceChange imprime: [name] sees [stockName] at $[price] - Making quick trade!
    • Una clase LongTermInvestor que implementa Investor. Tiene un campo name y su método onPriceChange imprime: [name] notes [stockName] at $[price] - Holding steady.
    • Una clase StockTicker (el sujeto) con:
      • Un campo String stockName
      • Una lista privada para almacenar a los inversores suscritos
      • Un método subscribe(Investor investor) para añadir un inversor
      • Un método unsubscribe(Investor investor) para eliminar un inversor
      • Un método updatePrice(double newPrice) que notifica a todos los inversores suscritos sobre el nuevo precio
  • main.dart: Importa tu sistema de acciones y demuestra el patrón Observer en acción:
    • Crea un StockTicker para una acción llamada DART
    • Crea un DayTrader llamado Alice y un LongTermInvestor llamado Bob
    • Suscribe a ambos inversores al ticker
    • Actualiza el precio a 150.50 (ambos inversores deben ser notificados)
    • Imprime una línea vacía
    • Desvincula (unsubscribe) a Alice del ticker
    • Actualiza el precio a 155.75 (ahora solo Bob debería ser notificado)

Esto demuestra cómo el patrón Observer crea un sistema débilmente acoplado: el StockTicker no necesita saber si está notificando a operadores diarios (day traders) o a inversores a largo plazo, ¡simplemente llama a onPriceChange en quien esté suscrito!

Salida 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.

Hoja de referencia

El patrón Observer establece una relación de uno a muchos donde un sujeto notifica a todos sus observadores cuando su estado cambia.

El patrón tiene dos roles clave:

  • Subject: Mantiene una lista de observadores y les notifica los cambios
  • Observer: Se registra con el sujeto y responde a las actualizaciones

Implementación 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');
  }
}

Beneficios clave:

  • Acoplamiento débil entre el sujeto y los observadores
  • Los observadores pueden suscribirse/desuscribirse dinámicamente
  • El sujeto no necesita conocer los tipos específicos de observadores

Pruébalo tú mismo

import 'stock_system.dart';

void main() {
  // TODO: Crear un StockTicker para una acción llamada 'DART'
  
  // TODO: Crear un DayTrader llamado 'Alice'
  
  // TODO: Crear un LongTermInvestor llamado 'Bob'
  
  // TODO: Suscribir a ambos inversores al ticker
  
  // TODO: Actualizar el precio a 150.50 (ambos inversores deben ser notificados)
  
  // TODO: Imprimir una línea vacía
  
  // TODO: Cancelar la suscripción de Alice del ticker
  
  // TODO: Actualizar el precio a 155.75 (ahora solo Bob debe ser notificado)
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos