Menu
Coddy logo textTech

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 investitori

Output:

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 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.

challenge icon

Sfida

Medio

Implementa 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)
  • 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
  • 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]C

Esempio 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.5C

Note importanti:

  • I metodi attach() e detach() 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

quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore Python online