Patrón Observer
Parte de la sección Object Oriented Programming 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 múltiples objetos (observadores) cuando su estado cambia.
Aquí hay 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 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 observer:
# Crear el sujeto
news = Subject()
# Crear los 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}")
# Use the stock tracker
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) # Notifies all investorsSalida:
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 $155Punto clave: El Patrón Observer permite que un objeto notifique a muchos otros automáticamente cuando algo cambia. El sujeto mantiene una lista de observadores y llama a su método update cuando es necesario. Esto es útil para notificaciones, sistemas de eventos y para mantener sincronizadas múltiples partes de su aplicación.
Desafío
IntermedioImplementa el Patrón Observer creando un sistema de monitoreo meteorológico. Debes crear dos clases en las áreas designadas del código.
Paso 1: Crear la clase WeatherStation
Escribe tu clase WeatherStation donde el comentario lo indica. Esta clase debe:
- Heredar de la clase Subject (usa
class WeatherStation(Subject):) - Inicializarse con:
- Llamar al constructor padre usando
super().__init__() - Establecer la temperatura inicial a 0 usando un atributo privado
self._temperature
- Llamar al constructor padre usando
- Implementar
<strong>set_temperature(self, temperature)</strong>:- Actualizar el atributo de temperatura privado
- Llamar a
self.notify(self._temperature)para notificar a todos los observadores
- Implementar
<strong>get_temperature(self)</strong>:- Retornar el valor de la temperatura actual
Paso 2: Crear la clase WeatherDisplay
Escribe tu clase WeatherDisplay donde el comentario lo indica. 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
- Aceptar un parámetro
- Implementar
<strong>update(self, temperature)</strong>:- Imprimir el mensaje de actualización de temperatura en el formato exacto 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]CEjemplo 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.5CNotas Importantes:
- Los métodos
attach()ydetach()ya están implementados en la clase base Subject; no necesitas implementarlos ni llamarlos dentro de 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 la temperatura cambia; la clase base Subject se encarga del resto - Enfócate en implementar los tres métodos requeridos en WeatherStation y los dos métodos requeridos en WeatherDisplay como se especificó anteriormente
Hoja de referencia
El Patrón Observer crea una relación de uno a muchos donde un objeto (sujeto) notifica a múltiples objetos (observadores) cuando su estado cambia.
Clase Subject básica 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)Clases Observer con el método update:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")Uso del patrón observer:
# 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!")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}")El Patrón Observer permite que un objeto notifique a muchos otros automáticamente cuando algo cambia. El sujeto mantiene una lista de observadores y llama a su método update cuando es necesario.
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í
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases vs ObjetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Resumen - Calculadora simple4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosResumen - Jerarquía de empleados7Métodos especiales
Introducción a los métodos mágicosSobrecarga de operadoresMétodos mágicos de contenedoresRepaso - Lista personalizada10Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy2Decoradores
Introducción a los decoradoresDecorador propertyDecorador de métodos estáticosDecorador de métodos de clase5Polimorfismo
Sobreescritura de métodos revisitadaDuck TypingClases y métodos abstractosDiseño de interfacesResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaMixinsMétodos estáticos y de claseDecoradores de claseGestores de contexto11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Propiedades de clase
Variables de instancia vs de claseDecoradores de propiedadesAtributos privadosResumen - Gestor de cuentas bancarias