Menu
CoddyTech

Patrón Observer (Eventos)

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 54 de 70.

El patrón Observer establece una relación de uno a muchos en la que un objeto (el sujeto) notifica a varios objetos dependientes (observadores) cuando cambia su estado. En C#, los eventos ofrecen una forma integrada de implementar este patrón con elegancia.

El patrón incluye un publicador que genera eventos y suscriptores que responden a ellos. Aquí tienes un ejemplo práctico de un monitor de precios de acciones:

public class Stock
{
    private decimal _price;
    
    public event Action<decimal> PriceChanged;
    
    public decimal Price
    {
        get => _price;
        set
        {
            _price = value;
            PriceChanged?.Invoke(_price);  // Notifica a todos los observadores
        }
    }
}

public class PriceAlert
{
    public void OnPriceChanged(decimal newPrice)
    {
        Console.WriteLine($"Alert: Price is now {newPrice}");
    }
}

public class PriceLogger
{
    public void OnPriceChanged(decimal newPrice)
    {
        Console.WriteLine($"Logged: {newPrice}");
    }
}

Los suscriptores asocian sus métodos al evento mediante += y pueden desasociarlos con -=:

var stock = new Stock();
var alert = new PriceAlert();
var logger = new PriceLogger();

stock.PriceChanged += alert.OnPriceChanged;
stock.PriceChanged += logger.OnPriceChanged;

stock.Price = 150.50m;
// Salida:
// Alerta: El precio es ahora 150.50
// Registrado: 150.50

stock.PriceChanged -= logger.OnPriceChanged;  // Cancelar la suscripción
stock.Price = 155.00m;
// Salida: Alerta: El precio es ahora 155.00

El patrón Observer fomenta un acoplamiento débil: la clase Stock no necesita saber nada sobre sus observadores. Los nuevos observadores pueden suscribirse sin modificar el publicador, lo que facilita ampliar y mantener el sistema.

challenge icon

Desafío

Fácil

Vamos a crear un sistema de monitoreo de temperatura usando el patrón Observer con eventos. Crearás un sensor que notifica a varios observadores cada vez que cambia la temperatura, perfecto para situaciones como los sistemas de control climático, donde distintos componentes deben reaccionar a las actualizaciones de temperatura.

Organizarás el código en tres archivos:

  • TemperatureSensor.cs: Crea una clase TemperatureSensor en el espacio de nombres Monitoring. Este es tu publicador: el sujeto que observarán otros objetos. Tu sensor debe tener:
    • Un campo privado para almacenar la temperatura actual
    • Un evento llamado TemperatureChanged que use Action<double> para notificar a los suscriptores sobre la nueva temperatura
    • Una propiedad Temperature que genere el evento cada vez que se establezca la temperatura en un nuevo valor
  • Observers.cs: Crea dos clases observadoras en el mismo espacio de nombres que se suscribirán a los cambios de temperatura:
    • DisplayUnit: tiene un método OnTemperatureChanged(double temp) que imprime Display: {temp}C
    • AlarmSystem: tiene un método OnTemperatureChanged(double temp) que imprime Alarm Check: {temp}C
  • Program.cs: Combina todo creando un sensor y ambos observadores. Suscribe a ambos observadores al evento del sensor y luego actualiza la temperatura. Después, cancela la suscripción del sistema de alarma y vuelve a actualizar la temperatura para mostrar que solo la unidad de visualización recibe la notificación.

Recibirás dos valores de entrada:

  • Primera lectura de temperatura (por ejemplo, 22.5)
  • Segunda lectura de temperatura (por ejemplo, 28.0)

Tu programa debe:

  1. Crear el sensor y ambos observadores
  2. Suscribir a ambos observadores al evento TemperatureChanged
  3. Establecer la temperatura del sensor en el primer valor de entrada (se debe notificar a ambos observadores)
  4. Cancelar la suscripción de AlarmSystem al evento
  5. Establecer la temperatura del sensor en el segundo valor de entrada (solo se debe notificar a la unidad de visualización)

Por ejemplo, si las entradas son 22.5 y 28.0, la salida debería ser:

Display: 22.5C
Alarm Check: 22.5C
Display: 28C

Esto demuestra el poder fundamental del patrón Observer: al sensor no le importa ni necesita saber quién lo está escuchando. Los observadores pueden suscribirse y cancelar su suscripción dinámicamente, y el publicador simplemente notifica a quienes estén escuchando en ese momento.

Pruébalo tú mismo

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // Lee las temperaturas de entrada
        double temp1 = Convert.ToDouble(Console.ReadLine());
        double temp2 = Convert.ToDouble(Console.ReadLine());

        // TODO: Crea una instancia de TemperatureSensor

        // TODO: Crea instancias de DisplayUnit y AlarmSystem

        // TODO: Suscribe ambos observadores al evento TemperatureChanged

        // TODO: Establece la temperatura del sensor en temp1 (se notifica a ambos observadores)

        // TODO: Cancela la suscripción de AlarmSystem al evento

        // TODO: Establece la temperatura del sensor en temp2 (solo se notifica a la pantalla)
    }
}
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

Practica por tu cuenta: Compilador de C# online