Observer-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 73 von 91.
Das Observer-Muster ist ein Verhaltensmuster, das eine Eins-zu-viele-Beziehung zwischen Objekten herstellt. Wenn ein Objekt (das Subjekt) seinen Zustand ändert, werden alle seine Abhängigen (die Beobachter) automatisch benachrichtigt und aktualisiert.
Denken Sie an ein Newsletter-Abonnement. Der Newsletter ist das Subjekt, und die Abonnenten sind die Beobachter. Wenn eine neue Ausgabe veröffentlicht wird, erhalten alle Abonnenten diese automatisch, ohne dass der Newsletter die Details jedes einzelnen Abonnenten kennen muss.
Hier ist eine grundlegende Implementierung in PHP:
<?php
interface Observer {
public function update(string $message): void;
}
class Newsletter {
private array $subscribers = [];
public function subscribe(Observer $observer): void {
$this->subscribers[] = $observer;
}
public function publish(string $content): void {
foreach ($this->subscribers as $subscriber) {
$subscriber->update($content);
}
}
}
class EmailSubscriber implements Observer {
public function __construct(private string $email) {}
public function update(string $message): void {
echo "Sending to {$this->email}: $message\n";
}
}
$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");
Ausgabe:
Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!Das Muster entkoppelt das Subjekt von seinen Beobachtern. Die Newsletter-Klasse muss nicht wissen, ob sie E-Mail-Abonnenten, SMS-Abonnenten oder Push-Benachrichtigungsdienste benachrichtigt. Sie ruft einfach update() für alles auf, was das Observer-Interface implementiert. Dies macht das Hinzufügen neuer Beobachtertypen mühelos, ohne den bestehenden Code zu ändern.
Aufgabe
EinfachLassen Sie uns ein Aktienkurs-Alarmsystem mit dem Observer Pattern erstellen. Wenn sich der Preis einer Aktie ändert, sollten alle registrierten Investoren automatisch benachrichtigt werden — eine perfekte reale Anwendung dieses Musters.
Sie werden Ihren Code über vier Dateien organisieren:
Observer.php— Definieren Sie einObserver-Interface mit einer einzigen Methodeupdate(string $stockName, float $price): void. Dies ist der Vertrag, dem alle Beobachter folgen müssen, um Benachrichtigungen zu erhalten.Investors.php— Binden Sie die Observer-Datei ein und erstellen Sie zwei Klassen, die das Interface implementieren:EmailInvestor— Nimmt eine E-Mail-Adresse in seinem Konstruktor entgegen (verwenden Sie Constructor Promotion). Seineupdate()-Methode gibt"Email to {$this->email}: {$stockName} is now \${$price}\n"aus.SmsInvestor— Nimmt eine Telefonnummer in seinem Konstruktor entgegen. Seineupdate()-Methode gibt"SMS to {$this->phone}: {$stockName} is now \${$price}\n"aus.
Stock.php— Binden Sie die Observer-Datei ein und erstellen Sie eineStock-Klasse, die als Subjekt fungiert. Ihre Aktie sollte:- Den Aktiennamen und den aktuellen Preis speichern (verwenden Sie Constructor Promotion für den Namen, initialisieren Sie den Preis auf
0.0) - Ein privates Array von Beobachtern verwalten
- Eine Methode
subscribe(Observer $observer): voidhaben, um Beobachter hinzuzufügen - Eine Methode
setPrice(float $price): voidhaben, die den Preis aktualisiert und alle Beobachter benachrichtigt
update()-Methode jedes Beobachters mit dem Aktiennamen und dem neuen Preis auf.- Den Aktiennamen und den aktuellen Preis speichern (verwenden Sie Constructor Promotion für den Namen, initialisieren Sie den Preis auf
main.php— Binden Sie die Dateien Investors und Stock ein. Sie erhalten drei Eingaben: einen Aktiennamen, eine E-Mail-Adresse und eine Telefonnummer.Erstellen Sie ein
Stock-Objekt mit dem angegebenen Namen. Abonnieren Sie einenEmailInvestormit der E-Mail-Adresse und einenSmsInvestormit der Telefonnummer.Setzen Sie den Aktienkurs auf
150.50, um Benachrichtigungen an alle Abonnenten auszulösen.
Das Observer Pattern hält Ihre Stock-Klasse von den spezifischen Benachrichtigungsmethoden entkoppelt. Sie könnten später problemlos einen PushInvestor oder SlackInvestor hinzufügen, ohne die Stock-Klasse überhaupt zu ändern.
Spickzettel
Das Observer Pattern (Beobachter-Muster) etabliert eine Eins-zu-viele-Beziehung, bei der ein Subjekt automatisch alle Beobachter benachrichtigt, wenn sich sein Zustand ändert.
Kernkomponenten:
- Observer Interface — Definiert den Vertrag für Beobachter mit einer
update()-Methode - Subject — Verwaltet eine Liste von Beobachtern und benachrichtigt diese über Zustandsänderungen
- Concrete Observers — Implementieren das Observer-Interface, um Benachrichtigungen zu erhalten
Grundlegende Implementierung:
<?php
interface Observer {
public function update(string $message): void;
}
class Subject {
private array $observers = [];
public function subscribe(Observer $observer): void {
$this->observers[] = $observer;
}
public function notify(string $data): void {
foreach ($this->observers as $observer) {
$observer->update($data);
}
}
}
class ConcreteObserver implements Observer {
public function __construct(private string $name) {}
public function update(string $message): void {
echo "Notifying {$this->name}: $message\n";
}
}
$subject = new Subject();
$subject->subscribe(new ConcreteObserver("Observer1"));
$subject->subscribe(new ConcreteObserver("Observer2"));
$subject->notify("State changed!");
Vorteile:
- Entkoppelt das Subjekt von seinen Beobachtern
- Einfaches Hinzufügen neuer Beobachtertypen ohne Änderung des bestehenden Codes
- Unterstützt dynamisches An- und Abmelden
Probier es selbst
<?php
require_once 'Investors.php';
require_once 'Stock.php';
// Eingaben lesen
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));
// TODO: Erstellen Sie eine Aktie (Stock) mit dem angegebenen Namen
// TODO: Abonnieren Sie einen EmailInvestor mit der E-Mail-Adresse
// TODO: Abonnieren Sie einen SmsInvestor mit der Telefonnummer
// TODO: Setzen Sie den Aktienkurs auf 150.50, um Benachrichtigungen auszulösen
?>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. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung