Menu
Coddy logo textTech

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.

challenge icon

Aufgabe

Einfach

Lassen 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 ein Observer-Interface mit einer einzigen Methode update(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). Seine update()-Methode gibt "Email to {$this->email}: {$stockName} is now \${$price}\n" aus.
    • SmsInvestor — Nimmt eine Telefonnummer in seinem Konstruktor entgegen. Seine update()-Methode gibt "SMS to {$this->phone}: {$stockName} is now \${$price}\n" aus.
  • Stock.php — Binden Sie die Observer-Datei ein und erstellen Sie eine Stock-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): void haben, um Beobachter hinzuzufügen
    • Eine Methode setPrice(float $price): void haben, die den Preis aktualisiert und alle Beobachter benachrichtigt
    Rufen Sie bei der Benachrichtigung der Beobachter die update()-Methode jedes Beobachters mit dem Aktiennamen und dem neuen 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 einen EmailInvestor mit der E-Mail-Adresse und einen SmsInvestor mit 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
?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung