Menu
Coddy logo textTech

Patrón Observer

Parte de la sección Programación orientada a objetos del Journey de Python de Coddy. Lección 47 de 64.

El patrón Observer crea una relación de uno a muchos en la que un objeto (sujeto) notifica a varios objetos (observadores) cuando cambia su estado.

Aquí tienes una clase Subject sencilla que gestiona observadores:

class Subject:
    def __init__(self):
        self._observers = []
    
    def add_observer(self, observer):
        self._observers.append(observer)
    
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

El sujeto mantiene una lista de observadores y puede notificarlos a todos a la vez.

Crea clases observadoras sencillas:

class EmailNotifier:
    def update(self, message):
        print(f"Email sent: {message}")

class SMSNotifier:
    def update(self, message):
        print(f"SMS sent: {message}")

Cada observador tiene un método update que se llama cuando recibe una notificación.

Usa el patrón observador:

# Crear sujeto
news = Subject()

# Crear observadores
email = EmailNotifier()
sms = SMSNotifier()

# Añadir observadores al sujeto
news.add_observer(email)
news.add_observer(sms)

# Notificar a todos los observadores
news.notify("Breaking news: Python is awesome!")

Crea un ejemplo práctico con un rastreador de precios de acciones:

class Stock:
    def __init__(self, symbol, price):
        self.symbol = symbol
        self._price = price
        self._observers = []
    
    def add_observer(self, observer):
        self._observers.append(observer)
    
    def set_price(self, price):
        self._price = price
        self.notify()
    
    def notify(self):
        for observer in self._observers:
            observer.update(self.symbol, self._price)

class Investor:
    def __init__(self, name):
        self.name = name
    
    def update(self, symbol, price):
        print(f"{self.name} notified: {symbol} is now ${price}")

# Usa el rastreador de acciones
apple_stock = Stock("AAPL", 150)

investor1 = Investor("Alice")
investor2 = Investor("Bob")

apple_stock.add_observer(investor1)
apple_stock.add_observer(investor2)

apple_stock.set_price(155)  # Notifica a todos los inversores

Salida:

Email sent: Breaking news: Python is awesome!
SMS sent: Breaking news: Python is awesome!
Alice notified: AAPL is now $155
Bob notified: AAPL is now $155

Punto clave: el patrón Observer permite que un objeto notifique automáticamente a muchos otros cuando algo cambia. El sujeto mantiene una lista de observadores y llama a su método update cuando es necesario. Esto resulta útil para las notificaciones, los sistemas de eventos y para mantener sincronizadas varias partes de tu aplicación.

challenge icon

Desafío

Intermedio

Implementa el patrón Observer creando un sistema de monitoreo meteorológico. Debes crear dos clases en las áreas designadas del código.

Paso 1: Crea la clase WeatherStation

Escribe tu clase WeatherStation donde lo indique el comentario. Esta clase debe:

  • Heredar de la clase Subject (usa class WeatherStation(Subject):)
  • Inicializarse con:
    • Llama al constructor de la clase padre usando super().__init__()
    • Establece la temperatura inicial en 0 usando un atributo con un solo guion bajo, self._temperature (la convención de Python para un atributo interno)
  • Implementar <strong>set_temperature(self, temperature)</strong>:
    • Actualiza el atributo de temperatura interno
    • Llama a self.notify(self._temperature) para notificar a todos los observadores
  • Implementar <strong>get_temperature(self)</strong>:
    • Devuelve el valor actual de la temperatura

Paso 2: Crea la clase WeatherDisplay

Escribe tu clase WeatherDisplay donde lo indique el comentario. Esta clase debe:

  • Heredar de la clase Observer (usa class WeatherDisplay(Observer):)
  • Inicializarse con:
    • Aceptar un parámetro name
    • Almacenar el nombre como self.name
  • Implementar <strong>update(self, temperature)</strong>:
    • Imprimir el mensaje de actualización de temperatura exactamente en el formato que se muestra a continuación

Formato del mensaje:

Cuando una pantalla recibe una actualización de temperatura, debe imprimir exactamente:

Display [name]: Current temperature is [temperature]C

Ejemplo de uso:

# Crear estación meteorológica y pantallas
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")

# Adjuntar pantallas a la estación
station.attach(phone_display)
station.attach(tablet_display)

# Actualizar temperatura - ambas pantallas serán notificadas
station.set_temperature(25.5)

# Salida:
# Display Phone: Current temperature is 25.5C
# Display Tablet: Current temperature is 25.5C

Notas importantes:

  • Los métodos attach() y detach() ya están implementados en la clase base Subject; no necesitas implementarlos ni llamarlos en tu clase WeatherStation
  • En el ejemplo de uso anterior, station.attach(phone_display) es llamado por el usuario de tu clase, no dentro de tu implementación de WeatherStation
  • Tu WeatherStation solo necesita llamar a self.notify() cuando cambie la temperatura; la clase base Subject se encarga del resto
  • Concéntrate en implementar los tres métodos requeridos en WeatherStation y los dos métodos requeridos en WeatherDisplay, tal como se especifica arriba

Pruébalo tú mismo

class Subject:
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        self._observers.append(observer)
        
    def detach(self, observer):
        self._observers.remove(observer)
        
    def notify(self, data):
        for observer in self._observers:
            observer.update(data)
            
class Observer:
    def update(self, data):
        pass

# Escribe tu clase WeatherStation aquí

# Escribe tu clase WeatherDisplay aquí

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 Python online