Observer-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 73 von 91.
Das Beobachter-Muster ist ein Verhaltensentwurfsmuster, das eine Eins-zu-viele-Beziehung zwischen Objekten herstellt. Wenn ein Objekt (das Subjekt) seinen Zustand ändert, werden alle seine abhängigen Objekte (die Beobachter) automatisch benachrichtigt und aktualisiert.
Stell dir ein Newsletter-Abonnement vor. Der Newsletter ist das Subjekt, und die Abonnenten sind Beobachter. Wenn eine neue Ausgabe veröffentlicht wird, erhalten alle Abonnenten sie automatisch, ohne dass der Newsletter die Details jedes 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 Klasse Newsletter muss nicht wissen, ob sie email-Abonnenten, SMS-Abonnenten oder Push-Benachrichtigungsdienste benachrichtigt. Sie ruft einfach update() für alles auf, was die Schnittstelle Observer implementiert. Dadurch lassen sich neue Beobachtertypen mühelos hinzufügen, ohne vorhandenen Code zu ändern.
Aufgabe
EinfachErstellen wir ein System zur Benachrichtigung über Aktienkurse mithilfe des Observer-Musters. Wenn sich der Kurs einer Aktie ändert, sollten alle registrierten Anleger automatisch benachrichtigt werden: eine perfekte Anwendung dieses Musters in der Praxis.
Du organisierst deinen Code über vier Dateien:
Observer.php: Definiere einObserver-Interface mit einer einzigen Methodeupdate(string $stockName, float $price): void. Dies ist der Vertrag, den alle Observer erfüllen müssen, um Benachrichtigungen zu erhalten.Investors.php: Binde die Observer-Datei ein und erstelle zwei Klassen, die das Interface implementieren:EmailInvestor: Nimmt in seinem Konstruktor eine E-Mail-Adresse entgegen (verwende Constructor Promotion). Seineupdate()-Methode gibt"Email to [email]: [stockName] is now $[price]"aus.SmsInvestor: Nimmt in seinem Konstruktor eine Telefonnummer entgegen. Seineupdate()-Methode gibt"SMS to [phone]: [stockName] is now $[price]"aus.
Stock.php: Binde die Observer-Datei ein und erstelle eineStock-Klasse, die als Subjekt fungiert. Deine Aktie sollte:- Den Namen der Aktie und den aktuellen Kurs speichern (verwende Constructor Promotion für den Namen und initialisiere den Kurs mit
0.0). - Ein privates Array von Observern verwalten.
- Eine
subscribe(Observer $observer): void-Methode zum Hinzufügen von Observern besitzen. - Eine
setPrice(float $price): void-Methode besitzen, die den Kurs aktualisiert und alle Observer benachrichtigt.
update()-Methode jedes Observers mit dem Namen der Aktie und dem neuen Kurs auf.- Den Namen der Aktie und den aktuellen Kurs speichern (verwende Constructor Promotion für den Namen und initialisiere den Kurs mit
main.php: Binde die Investors- und Stock-Dateien ein. Du erhältst drei Eingaben: einen Aktiennamen, eine E-Mail-Adresse und eine Telefonnummer.Erstelle eine
Stock-Instanz mit dem angegebenen Namen. Abonniere einenEmailInvestormit der E-Mail-Adresse und einenSmsInvestormit der Telefonnummer.Setze den Aktienkurs auf
150.50, um Benachrichtigungen an alle Abonnenten auszulösen.
Das Observer-Muster hält deine Stock-Klasse von den konkreten Benachrichtigungsmethoden entkoppelt. Du könntest später problemlos einen PushInvestor oder SlackInvestor hinzufügen, ohne die Stock-Klasse überhaupt zu ändern.
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: Erstelle eine Stock mit dem gegebenen Namen
// TODO: Abonniere einen EmailInvestor mit der E-Mail-Adresse
// TODO: Abonniere einen SmsInvestor mit der Telefonnummer
// TODO: Setze 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 OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler