Menu
Coddy logo textTech

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 donde un objeto (el sujeto) notifica a múltiples objetos dependientes (observadores) cuando su estado cambia. En C#, los eventos proporcionan una forma integrada de implementar este patrón de manera elegante.

El patrón involucra a un publicador que emite eventos y suscriptores que responden a ellos. Aquí hay 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);  // Notificar 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 utilizando += y pueden desvincularlos 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 ahora es 150.50
// Registrado: 150.50

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

El patrón Observer promueve el acoplamiento débil: la clase Stock no necesita saber nada sobre sus observadores. Nuevos observadores pueden suscribirse sin modificar al publicador, lo que hace que el sistema sea fácil de extender y mantener.

challenge icon

Desafío

Fácil

Construyamos 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 diferentes componentes deben reaccionar a las actualizaciones de temperatura.

Organizarás tu código en tres archivos:

  • TemperatureSensor.cs: Crea una clase TemperatureSensor en el espacio de nombres Monitoring. Este es tu publicador: el sujeto que otros objetos observarán. 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 de la nueva temperatura
    • Una propiedad Temperature que genere el evento cada vez que la temperatura se establezca 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: Une todo creando un sensor y ambos observadores. Suscribe ambos observadores al evento del sensor y, después, actualiza la temperatura. Luego, cancela la suscripción del sistema de alarma y actualiza la temperatura nuevamente para mostrar que solo la unidad de pantalla recibe la notificación.

Recibirás dos entradas:

  • 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 ambos observadores al evento TemperatureChanged
  3. Establecer la temperatura del sensor en el primer valor de entrada (ambos observadores deben recibir la notificación)
  4. Cancelar la suscripción de AlarmSystem al evento
  5. Establecer la temperatura del sensor en el segundo valor de entrada (solo la pantalla debe recibir la notificación)

Por ejemplo, si las entradas son 22.5 y 28.0, la salida debe 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 sabe quién lo está escuchando. Los observadores pueden suscribirse y cancelar su suscripción dinámicamente, y el publicador simplemente notifica a quien esté escuchando en ese momento.

Pruébalo tú mismo

using System;
using Monitoring;

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

        // TODO: Crear una instancia de TemperatureSensor

        // TODO: Crear instancias de DisplayUnit y AlarmSystem

        // TODO: Suscribir ambos observadores al evento TemperatureChanged

        // TODO: Establecer la temperatura del sensor a temp1 (ambos observadores notificados)

        // TODO: Desuscribir el AlarmSystem del evento

        // TODO: Establecer la temperatura del sensor a temp2 (solo el display 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

Practica por tu cuenta: Compilador de C# online