Menu
CoddyTech

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 de observador simples:

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 se le notifica.

Usa el patrón observador:

# Crea el sujeto
news = Subject()

# Crea los observadores
email = EmailNotifier()
sms = SMSNotifier()

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

# Notifica 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 es ú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 indica el comentario. Esta clase debe:

  • Heredar de la clase Subject (usa class WeatherStation(Subject):)
  • Inicializarse con:
    • Llamar al constructor de la clase padre mediante super().__init__()
    • Establecer 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 set_temperature(self, temperature):
    • Actualizar el atributo de temperatura interno
    • Llamar a self.notify(self._temperature) para notificar a todos los observadores
  • Implementar get_temperature(self):
    • Devolver el valor de la temperatura actual

Paso 2: Crea la clase WeatherDisplay

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

  • Heredar de la clase Observer (usa class WeatherDisplay(Observer):)
  • Inicializarse con:
    • Aceptar un parámetro name
    • Guardar el nombre como self.name
  • Implementar update(self, temperature):
    • 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:

# Create weather station and displays
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")

# Attach displays to station
station.attach(phone_display)
station.attach(tablet_display)

# Update temperature - both displays will be notified
station.set_temperature(25.5)

# Output:
# 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, el usuario de tu clase llama a station.attach(phone_display); no se llama dentro de tu implementación de WeatherStation
  • Tu WeatherStation solo necesita llamar a self.notify() cuando cambia 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 aquí tu clase WeatherStation

# Escribe aquí tu clase WeatherDisplay

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