Observer-Muster
Teil des Abschnitts Objektorientierte Programmierung der Python-Journey von Coddy. Lektion 47 von 64.
Das Observer-Muster stellt eine Eins-zu-viele-Beziehung her, bei der ein Objekt (Subjekt) mehrere Objekte (Beobachter) benachrichtigt, wenn sich sein Zustand ändert.
Hier ist eine einfache Subject-Klasse, die Beobachter verwaltet:
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)Das Subjekt führt eine Liste von Beobachtern und kann sie alle auf einmal benachrichtigen.
Erstelle einfache Beobachterklassen:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")Jeder Beobachter hat eine update-Methode, die aufgerufen wird, wenn er benachrichtigt wird.
Verwende das Beobachtermuster:
# Subjekt erstellen
news = Subject()
# Beobachter erstellen
email = EmailNotifier()
sms = SMSNotifier()
# Beobachter zum Subjekt hinzufügen
news.add_observer(email)
news.add_observer(sms)
# Alle Beobachter benachrichtigen
news.notify("Breaking news: Python is awesome!")Erstelle ein praktisches Beispiel mit einem Aktienkurs-Tracker:
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}")
# Verwende den Aktien-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) # Benachrichtigt alle InvestorenAusgabe:
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 $155Kernaussage: Das Beobachtermuster ermöglicht es einem Objekt, viele andere automatisch zu benachrichtigen, wenn sich etwas ändert. Das Subjekt führt eine Liste von Beobachtern und ruft bei Bedarf deren update-Methode auf. Das ist nützlich für Benachrichtigungen, Ereignissysteme und um mehrere Teile deiner Anwendung synchron zu halten.
Aufgabe
MittelImplementiere das Observer Pattern, indem du ein Wetterüberwachungssystem erstellst. Du musst zwei Klassen in den dafür vorgesehenen Bereichen des Codes erstellen.
Schritt 1: Erstelle die Klasse WeatherStation
Schreibe deine Klasse WeatherStation an der Stelle, die im Kommentar angegeben ist. Diese Klasse sollte:
- Von der Klasse Subject erben (verwende
class WeatherStation(Subject):) - Folgendermaßen initialisiert werden:
- Rufe den Konstruktor der übergeordneten Klasse mit
super().__init__()auf - Setze die Anfangstemperatur mithilfe des Attributs mit einfachem Unterstrich
self._temperatureauf 0 (Pythons Konvention für ein internes Attribut)
- Rufe den Konstruktor der übergeordneten Klasse mit
- Implementiere
set_temperature(self, temperature):- Aktualisiere das interne Temperaturattribut
- Rufe
self.notify(self._temperature)auf, um alle Beobachter zu benachrichtigen
- Implementiere
get_temperature(self):- Gib den aktuellen Temperaturwert zurück
Schritt 2: Erstelle die Klasse WeatherDisplay
Schreibe deine Klasse WeatherDisplay an der Stelle, die im Kommentar angegeben ist. Diese Klasse sollte:
- Von der Klasse Observer erben (verwende
class WeatherDisplay(Observer):) - Folgendermaßen initialisiert werden:
- Nimmt einen Parameter
nameentgegen - Speichert den Namen als
self.name
- Nimmt einen Parameter
- Implementiere
update(self, temperature):- Gib die Temperaturaktualisierungsnachricht genau im unten gezeigten Format aus
Nachrichtenformat:
Wenn eine Anzeige eine Temperaturaktualisierung erhält, muss sie genau Folgendes ausgeben:
Display [name]: Current temperature is [temperature]CBeispielverwendung:
# 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.5CWichtige Hinweise:
- Die Methoden
attach()unddetach()sind bereits in der Basisklasse Subject implementiert – du musst sie weder implementieren noch in deiner Klasse WeatherStation aufrufen - Im obigen Beispiel wird
station.attach(phone_display)vom Benutzer deiner Klasse aufgerufen, nicht innerhalb deiner WeatherStation-Implementierung - Deine WeatherStation muss nur
self.notify()aufrufen, wenn sich die Temperatur ändert – die Basisklasse Subject kümmert sich um den Rest - Konzentriere dich darauf, die drei erforderlichen Methoden in WeatherStation und die zwei erforderlichen Methoden in WeatherDisplay wie oben beschrieben zu implementieren
Probier es selbst
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
# Schreibe hier deine WeatherStation-Klasse
# Schreibe hier deine WeatherDisplay-Klasse
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDer self-ParameterMethodenAttributeKonstruktormethode (__init__)Zusammenfassung – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDie super()-FunktionMethodenüberschreibungMehrfachvererbungMethodenauflösungsreihenfolgeWiederholung – Mitarbeiterhierarchie7Spezielle Methoden
Einführung in magische MethodenOperatorüberladungMagische Methoden für ContainerRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformBankensystemEntwicklung von SpielfigurenFahrzeugvermietungsservice2Dekoratoren
Einführung in DekoratorenProperty-DekoratorDekorator für statische MethodenDekorator für Klassenmethoden5Polymorphie
Methodenüberschreibung erneut betrachtetDuck-TypingAbstrakte Klassen und MethodenSchnittstellendesignRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungMixinsStatische Methoden und KlassenmethodenKlassen-DekoratorenKontextmanager3Klassenattribute
Instanz- vs. KlassenvariablenProperty-DecoratorsPrivate AttributeWiederholung – Bankkontoverwaltung6Kapselung
Öffentliche, geschützte, private MemberZugriffsmodifikatorenInformationsverbergungProperty-Decorators – FortgeschrittenWiederholung – System zur Verwaltung von Studentendaten12Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und BenutzerklassenAusleihsystemSuchfunktionAdministrationsoberflächeTests und IntegrationÜbe selbstständig: Online-Python-Compiler