Concepto e introducción
En el diseño de sistemas, es común necesitar un módulo de notificación que permita distribuir mensajes del servidor a múltiples clientes. Una forma efectiva de abordar este escenario es mediante el uso del patrón observador (Observer), también conocido como patrón publicar-suscribir. Este patrón permite que varios observadores se registren para recibir notificaciones de un sujeto central cuando su estado cambia.
El patrón observador se define como:
Un patrón que establece una relación de uno a muchos entre objetos, de forma que cuando un objeto (sujeto) cambia su estado, todos los objetos dependientes (observadores) son notificados automáticamente.
Estructura del patrón
Los elementos clave del patrón observador son:
- Sujeto (Subject): Representa el objeto que mantiene el estado y notifica a los observadores sobre sus cambios.
- IObservador (Observer): Define una interfaz que los observadores deben implementar para recibir notificaciones.
- ObservadorConcreto (ConcreteObserver): Implementa la lógica de actualización cuando recibe una notificación.
Ejemplo práctico
Veamos un ejemplo sencillo que simula un sistema de notificaciones servidor-cliente.
Interfaz del cliente
public interface IObservador
{
void Actualizar(string mensaje);
}
Implementaciones concretas del observador
public class ClienteA : IObservador
{
public void Actualizar(string mensaje)
{
Console.WriteLine($"Cliente A recibió: {mensaje}");
}
}
public class ClienteB : IObservador
{
public void Actualizar(string mensaje)
{
Console.WriteLine($"Cliente B recibió: {mensaje}");
}
}
Clase del sujeto (servidor)
public class Servidor
{
public delegate void NotificacionHandler(string mensaje);
public static event NotificacionHandler NotificacionEvent;
public static void EnviarNotificacion(string mensaje)
{
NotificacionEvent?.Invoke(mensaje);
}
}
Uso del patrón
class Program
{
static void Main()
{
// Crear clientes
var clienteA = new ClienteA();
var clienteB = new ClienteB();
// Registrar observadores
Servidor.NotificacionEvent += clienteA.Actualizar;
Servidor.NotificacionEvent += clienteB.Actualizar;
// Enviar notificación
Servidor.EnviarNotificacion("¡Nuevo mensaje disponible!");
// Eliminar un observador
Servidor.NotificacionEvent -= clienteB.Actualizar;
// Enviar otra notificación
Servidor.EnviarNotificacion("Cliente B ya no recibirá mensajes.");
}
}
Ventajas y desventajas
Ventajas:
- Desacoplamiento entre el sujeto y los observadores.
- Soporte para comunicación uno a muchos sin necesidad de conocer cada observador.
- Fácil extensión: se pueden añadir nuevos observadores sin modificar el sujeto.
Desventajas:
- Puede haber problemas de rendimiento si hay muchos observadores, ya que el sujeto debe notificar a cada uno individualmente.
- La gestión incorrecta de suscripciones puede provocar fugas de memoria si no se eliminan correctamente los observadores.