Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Grundlagen der Programmierung: Entwurfsmuster

Beobachter: Lösung und praktische Umsetzung

Testen Sie unsere 2015 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Enge Kopplung und schlechte Erweiterbarkeit – das "Beobachter"-Muster hilft, beides zu vermeiden.
08:25

Transkript

Ich habe versucht eine Lösung dafür zu finden, einige Objekte hier eine Heizung und eine Kühlung davon zu informieren, wenn sich der Zustand eines anderen Objekts, in diesem Fall ist das hier der Temperatursensor, ändert. Jedes Mal wenn hier eine neue Temperatur reinkommt, dann sollen die beiden Geräte davon informiert werden, damit sie dann entsprechende Steuerentscheidungen treffen können. Im entsprechend Quelltext lässt sich sehr gut sehen, dass der Sensor dazu beide Interessenten sozusagen persönlich kennen muss. Er hat dafür diese zwei Attribute, in denen er sich merken kann, wo die Heizung und die Kühlung sich befinden. Bekommt diese Information im Constructor übergeben und verwendet sie hier, um diese beiden Geräte durch Aufruf einer entsprechenden Methode davon zu informieren, dass die Temperatur sich geändert hat. Möchten wir nun zum Beispiel einen weiteren Interessenten hinzufügen, muss also auch jedes Mal der Sensor entsprechend mitangepasst werden. Er benötigt ein weiteres Attribut, muss die Information im Constructor mitübergeben bekommen und auch hier müssen wir einen weiteren Aufruf hinzufügen. Diese Lösung ist also recht unflexibel und in diesem Video möchte ich Ihnen zeigen, wie sich das durch Anwenden des Beobachtermusters verbessern lässt. Gehen wir dazu nochmal zurück zur Ausgangssituation. Wir haben auf der einen Seite die Heizung und die Kühlung als Interessenten und auf der anderen Seite den Sensor. Nun machen wir folgendes. Wir fügen eine Schnittstelle hinzu, ein Interface, und in dieser Schnittstelle geben wir die Methode an, die der Sensor gerne aufrufen möchte. In diesem Fall also geänderteTemperatur. Da die Heizung und die Kühlung sich dafür interessieren, wann der Sensor seinen Zustand ändert, ihn also quasi beobachten um das rauszufinden, nenne ich diese Schnittstelle TemperaturBeobachter. Nun sorgen wir dafür, dass sowohl Heizung als auch Kühlung diese Schnittstelle anbieten. Das heißt, beide Objekte sind zwar Instanzen unterschiedlicher Klassen, haben aber trotzdem jetzt eine gemeinsame Schnittstelle. Auf diese Weise muss der Sensor nun nicht mehr die Namen der Klassen der einzelnen Interessenten wissen, sondern es genügt, wenn er die Schnittstelle TemperaturBeobachter kennt. Das ermöglicht es uns nun im Sensor auf Instanzvariablen von den konkreten Typen Heizung und Kühlung zu verzichten und dem Sensor stattdessen einfach eine Liste zu verpassen, in der er sich alle Interessenten merken kann. Da sowohl Heizung als auch Kühlung die Schnittstelle TemperaturBeobachter anbieten, genügt es auch vollkommen, wenn die Liste nur TemperaturBeobachter aufnehmen kann. Außerdem ist die Größe der Liste nicht auf zwei begrenzt und dadurch können wir hier prinzipiell beliebig viele Interessenten reinpacken. Wie kommen nun Heizung und Kühlung in die Liste? Dafür bietet der Sensor eine Methode anmelden an, mit der sich Objekte anmelden können. Melden wir nun also die Heizung beim Sensor an, dann gelangt sie auf diese Weise in die Liste und da liegt sie dann. Das Gleiche machen wir mit der Kühlung. Auch anmelden, auch die Kühlung kommt in die Liste und nun sind beide Interessenten beim Sensor angemeldet. Nun sitzen alle Objekte rum und warten, dass was passiert. Nach einer Weile passiert tatsächlich was. Die Temperatur ändert sich. Der Sensor nimmt nun seine Liste zur Hand und geht die Interessenten einen nach dem anderen durch. Er informiert sie davon, dass es eine neue Temperatur zu vermelden gibt, indem er die Methode aufruft, die in der Schnittstelle deklariert wurde. Zuerst wird also die Heizung informiert, danach die Kühlung. Damit sind wir dann auch schon wieder am Ende der Liste angekommen und alle Interessen sind erfolgreich informiert worden und auch das schauen wir uns natürlich jetzt wieder im Quelltext an. Wir beginnen mit der Deklaration der Schnittstelle TemperaturBeobachter. Die Schnittstelle legt fest, dass es eine Methode geben soll mit dem Namen geänderteTemperatur. Diese Methode soll ein int übernehmen und nichts zurückgeben. Die Änderungen, die wir an der Heizung vornehmen müssen, um dieses Muster jetzt anzuwenden, sind eigentlich recht minimal. Sie beschränken sich im Wesentlichen darauf, dass wir jetzt hier angeben müssen, dass die Heizung tatsächlich die Schnittstelle TemperaturBeobachter implementiert. Die Methode in der Interface Deklaration heißt zufällig genauso wie die Methode, die wir in der Heizung sowieso schon hatten, nämlich geänderteTemperatur. Das heißt, wir geben hier eigentlich nur noch an, dass wir tatsächlich die Interface Methode implementieren. Der Rest der Heizung bleibt unverändert. Das heißt, wir haben weiterhin hier unsere Temperatur, bei der die Heizung anspringen soll, ein Attribut, in dem sich die Heizung merkt, ob sie an oder aus ist, eine Methode zum Einschalten, eine zum Ausschalten und hier den komplexen Algorithmus, der anhand der aktuellen Temperatur entscheidet, was getan werden soll. Bei der Kühlung sieht es ganz genauso aus. Auch hier lediglich das Hinzufügen der Informationen, dass die Kühlung jetzt diese Schnittstelle anbietet und auch die Kühlung bleibt ansonsten unverändert. Beim Sensor sind die Änderungen allerdings umfangreicher. Die beiden Attribute, in denen sich der Sensor gemerkt hat, wo die Heizung und die Kühlung sich befinden, sind verschwunden, stattdessen haben wir jetzt hier die Liste, in der sich alle Beobachter befinden können. Damit sich die Beobachter jetzt anmelden können, gibt es im Sensor die Methode anmelden. Also Parameter wird der Beobachter übergeben und die Methode macht eigentlich nichts weiter, als den Beobachter der Liste hinzuzufügen. Wenn sich nun Interessenten zur Laufzeit des Programms anmelden können, dann ist es auch eine gute Idee, wenn sie sich wieder abmelden können. Ein Objekt, das sich nicht mehr dafür interessiert, ob es warm oder kalt ist, kann sich auf diese Weise vom Sensor abmelden und wird dann auch nicht mehr vom Sensor belästigt und schließlich müssen wir noch unsere Methode setTemperatur entsprechend anpassen. Bisher haben wir hier explizit Heizung und Kühlung informiert. Jetzt möchten wir einfach ganz allgemein alle Beobachter informieren. Das heißt, wir rufen hier die interne Methode informiereBeobachter auf, die sich hier unten befindet und die einfach nichts weiter tut, als durch die Liste der Beobachter durchzugehen und der Reihe nach von jedem Beobachter die in der Schnittstelle definierte Methode geänderteTemperatur aufruft und dann die Temperatur entsprechend übergibt. Wenn Sie sich das Ganze noch einmal anschauen, dann werden Sie jetzt sehen, dass im Temperatursensor sowohl Heizung als auch Kühlung nicht mehr vorkommen. Alles, was der Sensor jetzt noch weiß, ist, es gibt TemperaturBeobachter und die können sich an- und abmelden und wenn die Temperatur sich ändert, dann möchte sie gerne informiert werden. Jetzt wollen wir das natürlich noch ausprobieren, um zu sehen, ob es auch wirklich funktioniert. Ich habe hier dazu dieses kleine Testprogramm. Ich erzeuge zu Beginn eine Heizung und eine Kühlung und einen Sensor. Dem Sensor übergebe ich im Constructor nicht nur explizit, wen er informieren soll, sondern da mache ich durch eine Anzahl von Aufrufen der Methode anmelden, indem ich hier in diesem Beispiel Heizung und Kühlung übergebe. Danach machen wir einen kleinen Testlauf, indem wir dem Sensor der Reihe nach verschiedene Temperaturen mitteilen und schauen, was passiert. Bei 0 Grad sollte nichts passieren. Es ist zu warm für die Heizung und zu kalt für die Kühlung. Bei -20 Grad sollte dann die Heizung anspringen. Wenn die Heizung heizt, wird es wärmer. Bei +60 Grad sollte spätestens die Heizung ausgehen und die Kühlung an und wenn die Kühlung runterkühlt und wir sagen, jetzt sind 20 Grad erreicht, dann sollte auch die Kühlung wieder ausgehen. Probieren wir das Ganze aus und dann sehen wir, wenn der Sensor 0 Grad meldet, passiert gar nichts, wie erwartet. Bei -20 Grad geht die Heizung an. Bei 60 Grad geht die Heizung aus, die Kühlung an und bei 20 Grad geht die Kühlung wieder aus. Es funktioniert also tatsächlich alles so, wie es soll. In der ersten Lösung hatte uns gestört, dass es sehr schlecht erweiterbar ist. Wie sieht das hier nun aus? Ich habe dazu einen weiteren Beobachter vorbereitet und zwar eine simple Temperaturanzeige. Das ist ein ganz einfaches Objekt, das immer nur die aktuelle Temperatur anzeigt. Auch die Temperaturanzeige implementiert natürlich das Interface TemperaturBeobachter. Bietet also die Methode an und in der Methode wird einfach nur die aktuelle Temperatur ausgegeben. Um diese Anzeige jetzt mit dem Sensor bekannt zu machen, müssen wir im Sensor überhaupt nichts ändern. Die einzige Änderung haben wir hier in unserem Testprogramm und zwar müssen wir im Wesentlichen eigentlich nur überhaupt erst mal eine Anzeige erzeugen. Nachdem wir die Anzeige kreiert haben, müssen wir sie einfach noch beim Sensor anmelden. Ein letzter Testlauf, dann sehen wir, wenn der Sensor 0 Grad meldet, sagt uns die Anzeige, es sind gerade 0 Grad. Der Sensor meldet -20 Grad, dann meldet sich auch die Anzeige -20 Grad. Die Heizung funktioniert weiterhin. Bei 60 Grad sagt die Anzeige 60 Grad, Heizung geht aus, Kühlung geht an und bei 20 Grad sagt die Anzeige 20 Grad und die Kühlung geht aus. Sie sehen also, dass Beobachtermuster erfordert nur wenig mehr Aufwand bei der ersten Umsetzung. Wir müssen eine Schnittstelle hinzufügen und wir müssen im Sensor die Möglichkeit bieten, dass sich Beobachter an- und abmelden können. Dann ist es aber eine sehr flexible Lösung, weil wir quasi beliebig viele Beobachter an- und abmelden können und das Ganze sogar zur Laufzeit.

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 gute Einführung!!!
Armen Y.

Ich muss sagen, dass mir das Video überaus gut geholfen hat! Diese Vorstellung war um einiges besser als meine Vorlesung!! Der Aufbau "Problem" -> "Mögliche Loesung" -> "Nachteile" -> "Bessere Lösung" -> "Fazit" ist sehr verständlich und nachvollziehbar. Verwendete Grafiken: Sehr gut und sehr übersichtlich! Verwendeter Code: Sinnvoll, kompakt und verständlich! Dieses Video gehört (qualitativ betrachtet) zu den besten auf dieser Plattform!

 

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!