Beobachter (Entwurfsmuster)
Der Beobachter (engl. Observer) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung und gehört zu der Kategorie der Verhaltensmuster (Behavioural Patterns). Es ermöglicht die Propagierung von Änderungen eines Objekts an abhängige Objekte. Das Muster ist eines der sogenannten GoF-Muster (siehe Viererbande).
Verwendung
Anwendungsbeispiel
Eine oder auch mehrere Komponenten stellen den Status eines Objektes grafisch dar. Sie kennen die gesamte Schnittstelle dieses Objektes. Ändert sich der Status des Objektes, müssen die Komponenten darüber informiert werden. Anderseits soll das Objekt aber von den Komponenten unabhängig bleiben - ihre Schnittstelle also nicht kennen.
- Beispiel: Messergebnisse werden gleichzeitig in einem Balkendiagramm, einem Liniendiagramm und einer Tabelle dargestellt. Messwerte ändern sich permanent. Die Komponenten der Diagramme sollen diese Änderungen permanent darstellen, das gemessene Objekt soll aber keine Kenntnis über die Struktur dieser Komponenten besitzen.
Lösung
Das beobachtete Objekt bietet einen Mechanismus um Beobachter an- und abzumelden und diese über Änderungen zu informieren. Es kennt alle seine Beobachter nur über die (überschaubare) Schnittstelle Beobachter. Es meldet jede Änderung völlig unspezifisch an jeden angemeldeten Beobachter, braucht also die weitere Struktur dieser Komponenten nicht zu kennen.
Die Beobachter implementieren ihrerseits eine (spezifische) Methode, um auf die Änderung zu reagieren. In der Regel werden die für eine Komponente relevanten Teile des Status abgefragt.
Allgemeine Anwendungssituatuionen
Allgemein finden Beobachter Anwendung, wenn
- eine Abstraktion mehrere Aspekte hat, die von einem anderen Aspekt derselben Abstraktion abhängen,
- die Änderung eines Objekts Änderungen an anderen Objekten nach sich zieht oder
- ein Objekt andere Objekte benachrichtigen soll, ohne diese im Detail zu kennen.
UML-Diagramm
Akteure
- Subjekt
- kennt Liste von Beobachtern, aber keine konkreten Beobachter
- bietet Schnittstelle zur An- und Abmeldung von Beobachtern
- bietet Schnittstelle zur Benachrichtigung von Beobachtern "über Änderungen
- KonkretesSubjekt
- speichert relevanten Zustand
- benachrichtigt alle Beobachter bei Zustandsänderungen über deren Aktualisierungsschnittstelle
- Schnittstelle zur Erfragung des aktuellen Zustands
- Beobachter
- definiert Aktualisierungsschnittstelle
- KonkreterBeobachter
- verwaltet Referenz auf ein konkretes Subjekt, dessen Zustand es beobachtet
- speichert dessen Zustand konsistent
- implementiert Aktualisierungsschnittstelle unter Verwendung der Abfrageschnittstelle des konkreten Subjekts
Vorteile
- Subjekte und Beobachter können unabhängig variiert werden.
- Subjekt und Benutzer sind auf abstrakte und minimale Art lose gekoppelt. Das beobachtete Objekt braucht keine Kenntnis über die Struktur seiner Beobachter besitzen sondern kennt diese nur über die Beobachter-Schnittstelle.
- Ein abhängiges Objekt erhält die Änderungen automatisch.
- Broadcasts werden unterstützt.
Nachteile
- Änderungen am Objekt führen bei großer Beobachteranzahl zu hohen Änderungskosten. Einerseits informiert das Subjekt jeden Beobachter, auch wenn dieser die Änderungsinformation nicht benötigt. Zusätzlich können die Änderungen weitere Änderungen nach sich ziehen und so einen unerwartet hohen Aufwand haben.
- Ruft ein Beobachter während der Bearbeitung einer gemeldeten Änderung wiederum Änderungsmethoden des Subjektes auf, kann es zu Endlosschleifen kommen.
- Der Mechanismus liefert keine Information darüber, was sich geändert hat. Die daraus resultierende Unabhängigkeit der Komponenten kann sich allerdings auch als Vorteil herausstellen.
Beispiele
Implementation in Java
interface Beobachtbar { // b wird in die interne Liste der Beobachter aufgenommen public void meldeBeobachterAn(Beobachter b); // b wird aus der internen Liste der Beobachter entfernt public void meldeBeobachterAb(Beobachter b); // Für alle Beobachter der internen Liste wird die Methode "beachteAenderung" aufgerufen // diese Methode wird am Ende jeder verändernden Methode aufgerufen public void meldeAenderung(); }
interface Beobachter { // hier wird konkret implementiert, was eine Änderung für Folgen hat public void beachteAenderung(); }
Der Mechanismus der An- und Abmeldung sowie der Meldung ist völlig allgemein und könnte auch in einer konkreten Oberklasse vollständig implementiert werden. Das beobachtete Objekt würde dann nicht das Interface Beobachtbar implementieren, sondern von der Oberklasse Beobachtbar erben. In Java gibt es allerdings keine Mehrfachvererbung, so dass dieser Ansatz nur anwendbar ist, wenn keine weitere Vererbung vorgesehen ist.
Der Mechanismus der "Änderungsbeachtung" ist anwendungsabhängig und muss in jedem Fall konkret implementiert werden.
Listener und Events in Java
Java bietet fertige Observer und Observableklassen an, die der Entwickler verwenden kann.
Die Nachteile des Entwurfsmusters entfernt Java, indem es das Beobachterkonzept durch Listener und Events ersetzt. Interessiert sich eine Klasse für eine andere, implementiert sie deren Listener-interface und meldet sich beim Subjekt an. Ändert sich das Subjekt, informiert es seine Beobachter durch den Aufruf der Listenerschnittstelle, die die Änderung beschreibt.
Verwandte Entwurfsmuster
...