Observer-Muster
Teil des Abschnitts Objektorientierte Programmierung der Python-Journey von Coddy. Lektion 47 von 64.
Das Beobachter-Muster erstellt eine Eins-zu-viele-Beziehung, 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 verfügt über eine update-Methode, die aufgerufen wird, wenn er benachrichtigt wird.
Verwende das Beobachter-Muster:
# 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}")
# Aktien-Tracker verwenden
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 $155Wichtiger Punkt: Das Beobachter-Muster ermöglicht es einem Objekt, viele andere automatisch zu benachrichtigen, wenn sich etwas ändert. Das Subjekt verwaltet eine Liste von Beobachtern und ruft bei Bedarf deren update-Methode auf. Dies ist nützlich für Benachrichtigungen, Ereignissysteme und die Synchronisierung mehrerer Teile deiner Anwendung.
Aufgabe
MittelImplementiere das Observer Pattern, indem du ein System zur Wetterüberwachung erstellst. Du musst in den vorgesehenen Bereichen des Codes zwei Klassen erstellen.
Schritt 1: Erstelle die Klasse WeatherStation
Schreibe deine Klasse WeatherStation dort, wo der Kommentar darauf hinweist. Diese Klasse sollte:
- Von der Klasse Subject erben (verwende
class WeatherStation(Subject):) - Initialisiert werden mit:
- Rufe den Konstruktor der übergeordneten Klasse mit
super().__init__()auf - Setze die Anfangstemperatur mithilfe eines Attributs mit einfachem Unterstrich
self._temperatureauf 0 (Pythons Konvention für ein internes Attribut)
- Rufe den Konstruktor der übergeordneten Klasse mit
- Implementiere
<strong>set_temperature(self, temperature)</strong>:- Aktualisiere das interne Temperaturattribut
- Rufe
self.notify(self._temperature)auf, um alle Beobachter zu benachrichtigen
- Implementiere
<strong>get_temperature(self)</strong>:- Gib den aktuellen Temperaturwert zurück
Schritt 2: Erstelle die Klasse WeatherDisplay
Schreibe deine Klasse WeatherDisplay dort, wo der Kommentar darauf hinweist. Diese Klasse sollte:
- Von der Klasse Observer erben (verwende
class WeatherDisplay(Observer):) - Initialisiert werden mit:
- Einen
name-Parameter akzeptieren - Den Namen als
self.namespeichern
- Einen
- Implementiere
<strong>update(self, temperature)</strong>:- Gib die Nachricht zur Temperaturaktualisierung exakt im unten gezeigten Format aus
Nachrichtenformat:
Wenn ein Display eine Temperaturaktualisierung empfängt, muss es exakt Folgendes ausgeben:
Display [name]: Current temperature is [temperature]CBeispielverwendung:
# Wetterstation und Anzeigen erstellen
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")
# Anzeigen an Station anhängen
station.attach(phone_display)
station.attach(tablet_display)
# Temperatur aktualisieren – beide Anzeigen werden benachrichtigt
station.set_temperature(25.5)
# Ausgabe:
# 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 - In der obigen Beispielverwendung wird
station.attach(phone_display)vom Benutzer deiner Klasse aufgerufen, nicht innerhalb deiner Implementierung von WeatherStation - Deine Klasse WeatherStation muss nur
self.notify()aufrufen, wenn sich die Temperatur ändert – die Basisklasse Subject übernimmt den Rest - Konzentriere dich darauf, die drei erforderlichen Methoden in WeatherStation und die zwei erforderlichen Methoden in WeatherDisplay wie oben angegeben 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 deine WeatherStation-Klasse hier
# Schreibe deine WeatherDisplay-Klasse hier
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