Observer-Entwurfsmuster (Observer Pattern)
Observer-Entwurfsmuster (Observer Pattern)
Das Observer-Entwurfsmuster (deutsch: Beobachter-Muster) ist ein Verhaltensmuster, das verwendet wird, um eine eins-zu-viele-Abhängigkeit zwischen Objekten zu definieren. Wenn sich der Zustand eines Objekts (des Subjects) ändert, werden automatisch alle abhängigen Objekte (die Observer) benachrichtigt und aktualisiert.
Das Muster wird häufig für Ereignisbenachrichtigungen, GUI-Updates oder Echtzeitkommunikation eingesetzt.
Grundidee
Ein Objekt („Subject“) verwaltet eine Liste von Beobachtern („Observer“) und informiert sie, sobald sich sein Zustand ändert. Dadurch wird eine lose Kopplung zwischen Sender und Empfänger erreicht – das Subject kennt seine Observer nicht im Detail.
+-------------------+ +-------------------+ | Subject |<------>| Observer | |-------------------| |-------------------| | + attach() | | + update() | | + detach() | | | | + notify() | +-------------------+ +-------------------+
Struktur
| Komponente | Beschreibung |
|---|---|
| Subject | Verwaltet eine Liste von Observern und benachrichtigt sie bei Zustandsänderungen. |
| Observer | Definiert ein Interface zur Aktualisierung bei Benachrichtigung. |
| ConcreteSubject | Konkrete Implementierung des Subjects; speichert den Zustand. |
| ConcreteObserver | Beobachtet ein Subject und reagiert auf Benachrichtigungen. |
Beispiel (C++)
Ein einfaches Beispiel für das Observer-Muster in C++:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class Observer {
public:
virtual void update(const std::string& message) = 0;
virtual ~Observer() = default;
};
class Subject {
std::vector<Observer*> observers;
public:
void attach(Observer* obs) {
observers.push_back(obs);
}
void detach(Observer* obs) {
observers.erase(std::remove(observers.begin(), observers.end(), obs), observers.end());
}
void notify(const std::string& message) {
for (auto* obs : observers)
obs->update(message);
}
};
class ConcreteObserver : public Observer {
std::string name;
public:
explicit ConcreteObserver(std::string n) : name(std::move(n)) {}
void update(const std::string& message) override {
std::cout << name << " erhielt Nachricht: " << message << std::endl;
}
};
int main() {
Subject newsStation;
ConcreteObserver alice("Alice");
ConcreteObserver bob("Bob");
newsStation.attach(&alice);
newsStation.attach(&bob);
newsStation.notify("Neue Nachricht: Design Patterns erklärt!");
newsStation.detach(&bob);
newsStation.notify("Zweite Nachricht: Nur Alice wird benachrichtigt.");
}
Erklärung
In diesem Beispiel:
- Das
Subject(NewsStation) hält eine Liste von Beobachtern. - Bei einer Änderung ruft es
notify()auf. - Jeder
Observerwird mitupdate()benachrichtigt.
So bleibt das System flexibel: Neue Beobachter können leicht hinzugefügt oder entfernt werden, ohne das Subject zu verändern.
Vorteile
- Lose Kopplung zwischen Sender (Subject) und Empfänger (Observer)
- Beliebig viele Empfänger möglich
- Dynamisches An- und Abmelden der Beobachter
Nachteile
- Mögliche Performanceprobleme bei vielen Beobachtern
- Reihenfolge und Zeitpunkte der Benachrichtigungen sind nicht garantiert
- Kann zu unerwarteten Nebenwirkungen führen, wenn Beobachter ihrerseits wieder Benachrichtigungen auslösen
Typische Anwendungsfälle
- GUI-Systeme (z. B. Button → Listener)
- Event-Systeme (z. B. Message Bus, Signals/Slots)
- Datenbindung in MVVM-Architekturen
- Echtzeitbenachrichtigung (z. B. Wetterstation, Börsenticker)
Varianten
- Push-Modell: Das Subject sendet alle relevanten Daten mit der Benachrichtigung.
- Pull-Modell: Der Observer ruft die benötigten Daten beim Subject selbst ab.
Vergleich mit ähnlichen Mustern
| Muster | Vergleich |
|---|---|
| Mediator-Entwurfsmuster | Koordiniert mehrere Objekte zentral, anstatt direkte Benachrichtigungen zu senden. |
| Publisher-Subscriber-Muster | Ähnlich, aber häufig über einen Message-Bus oder Event-Queue realisiert. |
| Reactor-Entwurfsmuster | Ereignisgesteuert, aber auf System-Ebene (z. B. Socket-Ereignisse) statt auf Objektebene. |
Siehe auch
- Publisher-Subscriber-Muster
- Mediator-Entwurfsmuster
- Reactor-Entwurfsmuster
- Event-Driven Architecture
- Entwurfsmuster (Softwareentwicklung)
Quellen
- Erich Gamma et al.: *Design Patterns – Elements of Reusable Object-Oriented Software* (GoF, 1994)
- Wikipedia: Observer Pattern
- Refactoring.Guru: Observer Pattern