Grundlagen der Programmierung: Entwurfsmuster

Beobachter: Diskussion

Testen Sie unsere 1983 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Dieses Video fasst alle wichtigen Informationen zum "Beobachter" zusammen.
07:31

Transkript

Schauen wir uns alle wichtigen Informationen zum Beobachtermuster im Überblick an. Das Problem, das gelöst werden soll, ist folgendes. Wenn ein Objekt seinen Zustand ändert, dann sollen andere Objekte dafür informiert werden. Die Lösung, die wir gefunden haben, sieht so aus. Alle Interessenten haben eine gemeinsame Schnittstelle. In dieser Schnittstelle wird festgelegt, wie sie informiert werden können. Dann melden sie sich beim Objekt an, für dessen Zustand sie sich interessiere und wenn sich dann der Zustand des Objekts tatsächlich ändert, dann werden sie über die Methode, die in der Schnittstelle definiert wurde, informiert. Diese Lösung bietet eine Reihe von Vorteilen. Der wichtigste Punkt Beobachtetes und Beobachter sind voneinander entkoppelt. Beide Seiten kennen die lediglich die Schnittstelle und müssen nicht wissen, was dahinter passiert. Des Weiteren ist kein zusätzlicher Code notwendig, um dafür zu sorgen, dass bei jeder Zustandsänderung auch tatsächlich die Benachrichtigungen verschickt werden. Ändert sich der Zustand des Objekts, werden alle Benachrichtigungen automatisch verschickt. Ein wesentlicher Punkt ist, dass sowohl Art als auch Anzahl der Beobachter nicht eingeschränkt ist. Es ist völlig unerheblich, welcher Art die Beobachter sind, also Instanzen welcher Klassen sie sind. Alles was zählt ist, dass sie die richtige Schnittstelle implementieren. Schließlich müssen die Verdrahtungen zwischen den beiden Seiten nicht mehr hartcodiere, sondern wir können Beobachter zur Laufzeit an- und auch abmelden. Das klingt alles soweit ganz toll, aber in unserer Lösung hat sich momentan noch ein Problem versteckt. Hier haben wir die Klasse für den Temperatursensor, also für das Objekt, dessen Zustand sich ändert und das dann von den Beobachtern beobachtet werden soll. Das Problem, das man durchaus als schlechtestes Design bezeichnen könnte, ist folgendes. Wir haben hier sowohl technischen als auch fachlichen Code in einer Klasse vermischt. Fachlicher Code bedeutet, dass wofür der Temperatursensor als Temperatursensor eben gedacht ist, nämlich die Temperatur zu messen und sie sich intern zu merken. Das ist eigentlich alles, worum ein Temperatursensor sich kümmern sollte. All die anderen Dinge, also die Liste mit den Beobachtern, das Anmelden und das Abmelden von Beobachtern, das Informieren von Beobachtern ist alles technischer Code, der dadurch bedingt ist, dass wir hier das Beobachtermuster angewendet haben. Der Sensor versucht also eigentlich zwei Aufgaben zu lösen, die im engeren Sinne nichts miteinander zu tun haben. In einem sauberen Design sollte eine Klasse immer genau eine Verantwortlichkeit haben und dieses Prinzip haben wir hier offensichtlich verletzt. Stellen Sie sich vor, Sie haben nicht nur den Temperatursensor, sondern zum Beispiel auch einen Beschleunigungsmesser, einen Höhenmesser mit Luftdruckmessgerät und vielleicht auch noch einen Sensor für die Luftfeuchtigkeit. Da müssten Sie in jeder dieser Klassen diesen technischen Code immer wieder wiederholen. Das wäre dann sogar doppelt schlecht, weil wir sogar nicht Codedopplungen haben. Wenn ein Objekt versucht, zwei Aufgaben auf einmal zu lösen, die eigentlich nichts miteinander zu tun haben, dann sollten wir eine der Aufgaben in ein separates Objekt auslagern. In diesem Fall wäre das der Umstand, dass dieses Objekt beobachtet werden kann. Da das Objekt beobachtbar sein soll, können wir die Klasse einfach auch so nennen. Im Englischen wäre das dann observable. Schauen wir uns an, wie das im Quelltext aussieht. Dazu schließe ich die bisherigen Dateien und zeige Ihnen zuerst die geänderte Schnittstelle. Da das jetzt eine allgemeine Lösung sein soll, handelt es sich nicht mehr um einen TemperaturBeobachter sondern nur noch ganz allgemein um einen Beobachter. Der Beobachter soll einen geänderten Wert übermittelt bekommen können und um das Ganze möglichst flexibel und trotzdem typsicher zu machen, habe ich hier also einen generischen Typparameter verwendet. Das klingt möglicherweise komplizierter als es eigentlich ist. Ich zeige Ihnen das am Beispiel der Heizung. Die Heizung implementiert jetzt Beobachter und da wir die Temperatur hier in Form von ganzen Zahlen haben wollen, geben wir als Typ integer an. Das ist dann die Methode, die hier das Interface implementiert. Die hießt jetzt geaenderterWert, allgemeinerer Methodenname. Nimmt die neue Temperatur. Der Algorithmus ist der gleiche wie bisher. Auf Beobachterseite haben sich nur ein paar Bezeichnungen geändert, dadurch dass wir jetzt eine allgemeine Lösung haben wollen. Nun schauen wir uns an, wie das aussieht, wenn wir den technischen, der bisher im Sensor enthalten war, in eine separate Klasse auslagern. Das ist dann hier diese Klasse Beobachtbar. Diese Klasse stellt jetzt also die technische Infrastruktur zur Verfügung, damit sich Beobachter an- und abmelden können und damit sie alle informiert werden können. Auch hier haben wir wieder den Typparameter für den Typ des zu übermittelnden Wertes. Wir sehen hier die Liste für alle Beobachter wie bisher auch eine ganz normale ArrayList. Wir haben eine Methode zum Anmelden eines Beobachters. Der Beobachter wird als zur Liste hinzugefügt und eine Methode zum Abmelden des Beobachters. Der Beobachter wird also wieder aus der Liste entfernt. Und schließlich gibt es noch die Methode informiereBeobachter, die durch die Liste durchgeht und der Reihe nach alle Beobachter informiert. Bisher haben wir an dieser Stelle direkt die Temperatur übergeben und das geht jetzt natürlich nicht mehr, weil in dieser Klasse gibt es überhaupt keine Temperatur. Deswegen wird die hier als Parameter an informiereBeobachter übergeben und die Methode geht dann, wie gesagt, durch alle Elemente durch und übergibt diesen Wert an alle einzelnen Beobachter. Wenn wir uns nun den Temperatursensor anschauen, dann können wir sehen, dass er sich jetzt wieder auf seine reine Fachlichkeit konzentrieren kann. Er hat ein Attribut für die Temperatur. Es gibt eine Methode. Die heißt setTemperatur, die das Attribut auf den entsprechenden neuen Wert setzt. Er gibt uns seine Statusmeldung, in der er sagt neue Temperatur und dann ruft er die geerbte Methode informiereBeobachter auf. Damit ist alles aus dieser Klasse verschwunden, was irgendwie mit technischer Infrastruktur zu tun hat. Der Sensor kann sich also ganz auf seine Aufgabe konzentrieren. Temperatur messen und die Temperatur in die Runde rufen mit dieser Methode informiereBeobachter. Wir haben alle technischen Details in die Basisklasse Beobachtbar ausgelagert und der Sensor erbt jetzt diese Funktionalität. Muss sie also selbst nicht mehr zur Verfügung stellen. Wenn wir jetzt noch andere Sensoren zu unseren System hinzufügen wollen, dann müssen die ebenfalls lediglich von Beobachtbar erben und können sich jeweils auf ihre reine fachliche Aufgabe konzentrieren. Einen kleinen Wermutstropfen gibt es hier jetzt aber trotzdem noch und zwar aufgrund der Einfachvererbung. Die Basisklasse vom Temperatursensor muss beobachtbar sein und dadurch kann der Temperatursensor jetzt nicht mehr gleichzeitig noch von einer anderen Klasse erben. Sollte das stören, dann könnte man statt Vererbung Komposition in Betracht ziehen. In unserem Beispiel ist so was aber nicht nötig. Beim Beobachter, wie auch bei jedem anderen Muster, sollte man sich natürlich darüber im Klaren sein, dass die Verwendung nicht nur Vorteile sondern immer auch Nachteile mit sich bringt. Der erste Punkt wäre auf jeden Fall, wir haben eine zusätzliche Schnittstelle. Das ist jetzt aus Ihrer Sicht vielleicht nicht wirklich ein Nachteil, muss aber zumindest erwähnt werden. In größeren Anwendungen ist der Kontrollfluss schwerer nachvollziehbar. Wenn wir uns nur die Klasse Sensor anschauen, dann können wir nicht sehen, wer von diesem Sensor informiert wird. Wenn wir und die einzelnen Beobachter anschauen, dann wissen wir nicht, welcher Beobachter tatsächlich zur Laufzeit an- und abgemeldet ist. Eine saubere Dokumentation kann hier allerdings Abhilfe schaffen. Wie wir gerade gesehen haben, kann technischer und fachlicher Code im Beobachtenden vermischt werden. Wenn uns das stört, dann können wir den technischen Code in eine Basisklasse auslagern. Entscheiden wir uns für diesen Weg, dann müssen wir natürlich wieder daran denken, dass Einfachvererbung es verhindert, dass weitere Oberklassen für das zu beobachtende Objekt verwendet werden können. Vorausgesetzt natürlich wir nutzen eine Programmiersprache, die nur Einfachvererbung zulässt, wie das bei Java zum Beispiel der Fall ist. Und schließlich sollte man nicht vergessen, dass in unserer Anwendung nichts parallel läuft. Das heißt, alle Beobachter werden nacheinander informiert. Braucht ein Beobachter also sehr lange für die Bearbeitung der Information, dann würde er damit alle nachfolgenden Beobachter entsprechend blockieren. Wenn die Bearbeitung tatsächlich sehr umfangreich sein sollte, dann könnte eine asynchrone Abarbeitung in einem separaten Thread eine Lösungsmöglichkeit darstellen. Damit kennen Sie jetzt nun das Entwurfsmuster Beobachter und wissen auch, wie Sie es in der Praxis umsetzen können.

Grundlagen der Programmierung: Entwurfsmuster

Erhalten Sie einen fundierten Einstieg in das Thema Entwurfsmuster (Design Patterns) und erfahren Sie, wie Sie Entwurfsmuster in objektorientierten Programmiersprechen umsetzen.

2 Std. 49 min (33 Videos)
Sehr sehr gutes Training!
DHBW-Stuttgart

Vielen Dank für dieses tolle Training! Selbst nach vielen Stunden lernen und einer geschriebenen Klausur hatte ich das Thema nicht wirklich verstanden. Jetzt vor meiner Abschlussprüfung habe ich, dank deiner Videos, endlich verstanden wofür die verschiedenen Entwurfsmuster gut sind und welche Vor- und Nachteile bieten. Chapeau! Viele Grüße!

 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!