Alle erfahren vom neuen Raum
Das Beobachtermuster (Observer) sorgt dafür, dass ein Objekt viele andere über eine Änderung informiert, ohne sie zu kennen. Das Zustandsmuster (State) lässt ein Objekt je nach Phase anders reagieren.
Der Raum einer Vorlesung ändert sich. Der Aushang, das Handy und die Webseite sollen es sofort zeigen. Eine Bestellung wiederum verhält sich je nach Phase anders.
Am Ende dieser Lektion
Notiz
Ich kann das Beobachtermuster und das Zustandsmuster anwenden.
Schlüsselwörter
| Begriff | Was er bedeutet |
|---|---|
| Beobachter | ein Objekt, das über Änderungen informiert werden will |
| Anmelden | sich in die Liste der Beobachter eintragen lassen |
| Benachrichtigung | der Aufruf, mit dem alle Beobachter von einer Änderung erfahren |
| Zustand | die Phase, in der sich ein Objekt gerade befindet |
| Übergang | der Wechsel von einem Zustand in den nächsten |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Beobachter erfahren von einer Änderung, ohne zu fragen
Das Problem: Ein Objekt ändert sich, und mehrere andere müssen es wissen. Fragt jedes ständig nach, kostet das Zeit. Kennt das Objekt alle anderen fest, hängt es von ihnen ab.
Beim Beobachtermuster führt das Objekt eine Liste. Wer sich anmeldet, steht darin. Bei einer Änderung ruft es bei jedem Eintrag melden auf.
Ein Stundenplan mit zwei Beobachtern
class Stundenplan:
def __init__(self):
self.beobachter = []
def anmelden(self, beobachter):
self.beobachter.append(beobachter)
def raum_aendern(self, fach, raum):
for beobachter in self.beobachter:
beobachter.melden(fach, raum)
class Aushang:
def melden(self, fach, raum):
print("Aushang: " + fach + " jetzt in " + raum)
class Handy:
def __init__(self, name):
self.name = name
def melden(self, fach, raum):
print(self.name + " erhält: " + fach + ", Raum " + raum)
plan = Stundenplan()
plan.anmelden(Aushang())
plan.anmelden(Handy("Mia"))
plan.raum_aendern("Mathe", "B12")
# Melden Sie ein zweites Handy an und ändern Sie den Raum noch einmal.
Was beim Raumwechsel passiert
| Schritt | Wer | Was geschieht |
|---|---|---|
| 1 | Aushang | meldet sich mit anmelden an |
| 2 | Handy von Mia | meldet sich an |
| 3 | Stundenplan | raum_aendern("Mathe", "B12") läuft |
| 4 | Stundenplan | ruft melden bei Aushang und Handy auf, in der Reihenfolge der Anmeldung |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele vergessen das Abmelden. Ein Beobachter, der nicht mehr gebraucht wird, steht dann weiter in der Liste und bekommt jede Nachricht. Bieten Sie neben anmelden immer auch abmelden an.
Zustandsmuster: je Phase ein Objekt
Das Problem: Eine Bestellung ist offen, bezahlt oder versendet. Was erlaubt ist, hängt davon ab. Eine Kette von if zustand == ... steht dann in jeder Methode.
Beim Zustandsmuster ist jede Phase ein eigenes Objekt mit denselben Methoden. Die Bestellung hält das aktuelle Zustandsobjekt und gibt Aufrufe an es weiter. Ein Übergang heißt: Das Zustandsobjekt nennt den nächsten.
Eine Bestellung wechselt ihre Phase
class Offen:
def name(self):
return "offen"
def weiter(self):
return Bezahlt()
class Bezahlt:
def name(self):
return "bezahlt"
def weiter(self):
return Versendet()
class Versendet:
def name(self):
return "versendet"
def weiter(self):
return self
class Bestellung:
def __init__(self):
self.zustand = Offen()
def weiter(self):
self.zustand = self.zustand.weiter()
bestellung = Bestellung()
for schritt in range(4):
print(bestellung.zustand.name())
bestellung.weiter()
Die Zustände der Bestellung im Überblick
| Zustand | name() liefert | weiter() liefert |
|---|---|---|
| Offen | offen | Bezahlt |
| Bezahlt | bezahlt | Versendet |
| Versendet | versendet | sich selbst, die Bestellung ist am Ende |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Ampel und eine Quelle im Lab
Im Lab laufen zwei kleine Programme. Die Datei ampel.py zeigt eine Ampel als Zustandsobjekte: Rot, Gruen, Gelb, und dann wieder Rot.
Die Datei quelle.py zeigt einen Beobachter ohne Klasse: Zwei Funktionen melden sich an. Die Ausgabe folgt aus den Programmen selbst.
Den Ordner anlegen
mkdir -p ~/oop-laborHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Hineingehen
cd ~/oop-laborHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ampel mit drei Zuständen schreiben
printf 'class Rot:\n def weiter(self):\n return Gruen()\n\n def farbe(self):\n return "Rot"\n\nclass Gruen:\n def weiter(self):\n return Gelb()\n\n def farbe(self):\n return "Gruen"\n\nclass Gelb:\n def weiter(self):\n return Rot()\n\n def farbe(self):\n return "Gelb"\n\nzustand = Rot()\nfor schritt in range(5):\n print(schritt, zustand.farbe())\n zustand = zustand.weiter()\n' > ampel.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ampel starten
python3 ampel.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Eine Quelle mit zwei Beobachtern schreiben
printf 'class Quelle:\n def __init__(self):\n self.hoerer = []\n\n def anmelden(self, hoerer):\n self.hoerer.append(hoerer)\n\n def senden(self, text):\n for hoerer in self.hoerer:\n hoerer(text)\n\ndef erster(text):\n print("Erster: " + text)\n\ndef zweiter(text):\n print("Zweiter: " + text)\n\nquelle = Quelle()\nquelle.anmelden(erster)\nquelle.anmelden(zweiter)\nquelle.senden("Hallo")\nquelle.hoerer.remove(erster)\nquelle.senden("Tschuess")\n' > quelle.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Quelle starten
python3 quelle.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Beobachter müssen keine Klassen sein
Die Quelle ruft jeden Eintrag wie eine Funktion auf. Es genügt also eine Funktion, die einen Text annimmt. Nach dem Abmelden hört nur noch zweiter zu: Zweiter: Tschuess.
Die Ampel zeigt: Jedes Zustandsobjekt kennt nur seinen Nachfolger. Ein vierter Zustand ändert nur den Zustand davor.