Modello Observer
Fa parte della sezione Programmazione orientata agli oggetti del percorso Python di Coddy. Lezione 47 di 64.
Il pattern Observer crea una relazione uno-a-molti in cui un oggetto (soggetto) notifica più oggetti (osservatori) quando il suo stato cambia.
Ecco una semplice classe Subject che gestisce gli osservatori:
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)Il soggetto mantiene un elenco di osservatori e può avvisarli tutti in una volta.
Crea semplici classi osservatore:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")Ogni osservatore ha un metodo update che viene chiamato quando riceve una notifica.
Usa il pattern Observer:
# Crea il soggetto
news = Subject()
# Crea gli osservatori
email = EmailNotifier()
sms = SMSNotifier()
# Aggiungi gli osservatori al soggetto
news.add_observer(email)
news.add_observer(sms)
# Notifica tutti gli osservatori
news.notify("Breaking news: Python is awesome!")Crea un esempio pratico con un monitoraggio del prezzo delle azioni:
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 il tracker delle azioni
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 tutti gli investitoriOutput:
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 chiave: il pattern Observer consente a un oggetto di notificare automaticamente molti altri quando qualcosa cambia. Il soggetto mantiene un elenco di osservatori e chiama il loro metodo update quando necessario. È utile per le notifiche, i sistemi di eventi e per mantenere sincronizzate più parti della tua applicazione.
Sfida
MedioImplementa il pattern Observer creando un sistema di monitoraggio meteorologico. Devi creare due classi nelle aree designate del codice.
Passaggio 1: crea la classe WeatherStation
Scrivi la classe WeatherStation dove indicato dal commento. Questa classe deve:
- Ereditare dalla classe Subject (usa
class WeatherStation(Subject):) - Inizializzarsi con:
- Chiamare il costruttore della classe genitore usando
super().__init__() - Impostare la temperatura iniziale a 0 usando un attributo con un singolo trattino basso
self._temperature(convenzione Python per un attributo interno)
- Chiamare il costruttore della classe genitore usando
- Implementare
<strong>set_temperature(self, temperature)</strong>:- Aggiornare l'attributo della temperatura interna
- Chiamare
self.notify(self._temperature)per notificare tutti gli osservatori
- Implementare
<strong>get_temperature(self)</strong>:- Restituire il valore attuale della temperatura
Passaggio 2: crea la classe WeatherDisplay
Scrivi la classe WeatherDisplay dove indicato dal commento. Questa classe deve:
- Ereditare dalla classe Observer (usa
class WeatherDisplay(Observer):) - Inizializzarsi con:
- Accettare un parametro
name - Memorizzare il nome in
self.name
- Accettare un parametro
- Implementare
<strong>update(self, temperature)</strong>:- Stampare il messaggio di aggiornamento della temperatura nel formato esatto mostrato di seguito
Formato del messaggio:
Quando un display riceve un aggiornamento della temperatura, deve stampare esattamente:
Display [name]: Current temperature is [temperature]CEsempio d'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.5CNote importanti:
- I metodi
attach()edetach()sono già implementati nella classe base Subject: non devi implementarli né chiamarli nella classe WeatherStation - Nell'esempio d'uso qui sopra,
station.attach(phone_display)viene chiamato dall'utente della tua classe, non all'interno della tua implementazione di WeatherStation - La tua WeatherStation deve solo chiamare
self.notify()quando la temperatura cambia: la classe base Subject si occupa del resto - Concentrati sull'implementazione dei tre metodi richiesti in WeatherStation e dei due metodi richiesti in WeatherDisplay, come specificato sopra
Provalo tu
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
# Scrivi qui la tua classe WeatherStation
# Scrivi qui la tua classe WeatherDisplay
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP
File esterniIntroduzione a OOPClassi vs. oggettiIl parametro selfMetodiAttributiMetodo costruttore (__init__)Riepilogo - Calcolatrice semplice4Ereditarietà
Ereditarietà di baseLa funzione super()Sovrascrittura dei metodiEreditarietà multiplaOrdine di risoluzione dei metodiRiepilogo - Gerarchia dei dipendenti7Metodi speciali
Introduzione ai metodi magiciSovraccarico degli operatoriMetodi magici dei contenitoriRiepilogo - Lista personalizzata10Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello ObserverModello Strategy2Decoratori
Introduzione ai decoratoriDecoratore di proprietàDecoratore di metodo staticoDecoratore di metodo di classe5Polimorfismo
Ripasso dell'override dei metodiDuck typingClassi e metodi astrattiProgettazione delle interfacceRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàMixinMetodi statici e di classeDecorator di classeContext manager11Pattern di progettazione - Parte 2
Pattern dei comandiPattern adattatorePattern decoratorePattern metodo templatePattern statoPattern composito3Proprietà delle classi
Variabili di istanza e di classeDecorator delle proprietàAttributi privatiRiepilogo - Gestore di conti bancari6Incapsulamento
Membri pubblici, protetti e privatiModificatori di accessoOccultamento delle informazioniDecorator delle proprietà: avanzatiRipasso - Sistema di registri degli studenti12Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e UtenteSistema di prestitoFunzionalità di ricercaInterfaccia amministratoreTest e integrazioneEsercitati da solo: Compilatore Python online