Übungsaufgaben zum Entwurfsmuster Beobachter (Observer)

https://bildung.social/@oerinformatik/

https://oer-informatik.de/entwurfsmuster-observer-uebungsaufgaben

Entwurfsmuster, Beobachter-Muster, Observer, UML-Klassendiagramm, UML-Sequenzdiagramm, Pseudocode, Push- und Pull-Modell, MVC, Übungsaufgaben, Prüfungsvorbereitung

tl/dr; (Bearbeitungszeit insgesamt 81 min, mehrere Aufgaben): Zwei umfangreiche Übungsaufgaben zum Beobachter-Muster: Benachrichtigungen bei verschobenen oder abgesagten Aktivitäten einer Freizeit-App mit Klassendiagramm, Pseudocode, Sequenzdiagramm und Fehlersuche sowie der Fertigungsfortschritt im Kundenkonto eines Fahrrad-Onlineshops mit abstrakter Subjekt-Klasse, Push- und Pull-Modell, MVC und Datenbindung. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 28.10.2026)

Diese Übungsaufgaben gehören zum Artikel Entwurfsmuster Beobachter (Observer). Sie bauen auf den Artikeln Entwurfsmuster: Strategie, Zustand, Proxy und Dekorierer und UML-Sequenzdiagramme auf.

Hinweise zur Bearbeitung: Von FIA wird erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1 und Aufgabe 3.2) keine Probleme bereiten. Zeichne Deine Ergänzungen der Diagramme auf Papier oder mit einem Werkzeug Deiner Wahl, bevor Du die Beispiellösung aufklappst. Gib Methoden mit vollständiger Signatur an. Pseudocode muss keiner bestimmten Sprache folgen, aber erkennbar mit Objekten, Methodenaufrufen und Schleifen arbeiten; Listen beginnen beim Index 0. Andere fachlich richtige Lösungen sind ebenfalls richtig.

Code und Beispiellösungen kannst Du in vier Pseudocode-Notationen anzeigen lassen, hier am Beispiel einer Zuweisung; für Deine eigenen Lösungen darfst Du eine davon wählen. Die Notationen sind im Artikel Algorithmen mit Pseudocode dokumentieren beschrieben.

status: string := "abgesagt"

Aufgabe 3.1: Verschobene und abgesagte Aktivitäten in einer Freizeit-App (Profilkompetenz)

(ca. 45 min Bearbeitungszeit)

Du bist Auszubildende*r im Entwicklungsteam der Let’s Meet GmbH in Bielefeld. Die App „Let’s Meet“ bringt Menschen für gemeinsame Freizeitaktivitäten zusammen. Bisher erfahren Teilnehmende nur durch Zufall, wenn eine Aktivität verschoben oder abgesagt wird. Clara Neumann, Geschäftsführerin und Product Owner, wünscht sich: „Wenn sich an einer Aktivität etwas ändert, müssen alle Stellen in der App sofort Bescheid wissen – Push-Hinweis, Kalender, und demnächst auch der Gruppenchat und die Warteliste.“

Yusuf Demir, Leiter der Entwicklung und Dein Ausbilder, möchte dafür ein Entwurfsmuster einsetzen, damit die Klasse Aktivitaet nicht bei jeder neuen Benachrichtigungsart geändert werden muss.

  1. Nenne ein geeignetes Entwurfsmuster für diese Anforderung und begründe Deine Wahl am Beispiel der App. (4 Punkte)

Muster (1 Punkt): Beobachter (Observer), ein Verhaltensmuster.

Begründung (3 Punkte), z. B.:

  • Es besteht eine 1-zu-n-Abhängigkeit: Ändert sich eine Aktivität (verschoben, abgesagt), müssen mehrere andere Objekte reagieren (Push-Hinweis, Kalender, später Chat und Warteliste).

  • Das Muster sorgt dafür, dass alle angemeldeten Beobachter automatisch benachrichtigt werden, sobald Aktivitaet sich ändert.

  • Aktivitaet kennt die Benachrichtigungsarten nur über ein gemeinsames Interface (lose Kopplung). Chat-Hinweis und Wartelisten-Anzeige können später als neue Beobachter ergänzt werden, ohne Aktivitaet zu ändern.

Je sinnvollem, auf das Beispiel bezogenem Argument 1 Punkt.

Yusuf hat einen ersten Entwurf erstellt. Die Zustandslogik der Aktivität ist darin ausgeblendet; der Status wird hier nur als Text ("geplant", "abgesagt" …) abgefragt. Die Klasse KalenderFeed schreibt den Termin in den Kalender-Abonnementlink, den Teilnehmende in ihre Kalender-App einbinden können.

Vorgabe: Interfaces Subject und Observer, Klasse Aktivitaet realisiert Subject, PushHinweis und KalenderFeed realisieren Observer; Beziehung zwischen Aktivitaet und Observer sowie einige Methoden fehlen (mit KI erstellt)
  1. Ordne in der Tabelle jedem Element des Entwurfs seine Rolle im Entwurfsmuster zu. (2,5 Punkte)
Elemente des Entwurfs und ihre Rollen (zum Ausfüllen)
Element Rolle im Muster
Subject
Aktivitaet
Observer
PushHinweis
KalenderFeed

Je Zeile 0,5 Punkte:

Lösung: Elemente des Entwurfs und ihre Rollen
Element Rolle im Muster
Subject Subjekt (Interface des beobachteten Objekts)
Aktivitaet konkretes Subjekt (wird beobachtet, verwaltet die Beobachter)
Observer Beobachter (Interface)
PushHinweis konkreter Beobachter
KalenderFeed konkreter Beobachter
  1. Ergänze im Klassendiagramm die Beziehung zwischen Aktivitaet und dem Interface Observer mit Multiplizitäten und füge in den Klassen Aktivitaet, PushHinweis und KalenderFeed die jeweils fehlenden Methoden ein. (5 Punkte)
Lösung: Aktivitaet aggregiert beliebig viele Observer und enthält addObserver, removeObserver und notifyObservers; PushHinweis und KalenderFeed enthalten update (mit KI erstellt)

Bewertung (5 Punkte):

  • Aggregation zwischen Aktivitaet und Observer, hohle Raute an Aktivitaet (1 Punkt), Multiplizität 0..* beim Observer (0,5 Punkte), Multiplizität bei Aktivitaet (0..* oder 1, 0,5 Punkte); eine Komposition ist fachlich schwächer, wird aber noch mit 0,5 Punkten für das Symbol bewertet

  • Aktivitaet: +addObserver(o: Observer), +removeObserver(o: Observer), +notifyObservers() je 0,5 Punkte (1,5 Punkte)

  • PushHinweis und KalenderFeed: je +update() (2 × 0,75 Punkte)

Typische Fehler: Raute am Interface; update() nur im Interface, nicht in den realisierenden Klassen; die Methoden des Subjekt-Interfaces in Aktivitaet vergessen, weil die Klasse schon viele Einträge hat.

  1. Erläutere die Art der Beziehung zwischen der Klasse Aktivitaet und dem Interface Subject. (2 Punkte)

Es handelt sich um eine Realisierung (Schnittstellenimplementierung) (1 Punkt). Subject ist ein Interface: Es legt nur fest, welche Methoden es gibt, von ihm selbst können keine Objekte erzeugt werden. Aktivitaet verpflichtet sich, alle abstrakten Methoden des Interfaces – addObserver, removeObserver, notifyObservers – zu implementieren (1 Punkt). Aktivitäten können dadurch überall verwendet werden, wo ein Subject erwartet wird.

  1. Erläutere die Art der Beziehung zwischen der Klasse PushHinweis und dem Interface Observer. Begründe, warum diese Art der Beziehung hier sinnvoll ist. (4 Punkte)

Erläuterung (2 Punkte): Realisierung bzw. Schnittstellenimplementierung. PushHinweis muss die abstrakte Methode update() des Interfaces Observer implementieren und übernimmt damit die Rolle eines Beobachters.

Begründung (2 Punkte): notifyObservers() in Aktivitaet ruft bei allen Objekten in der Liste observers die Methode update() auf, ohne deren Klasse zu kennen. Dank Polymorphie wird zur Laufzeit die jeweils passende Implementierung ausgeführt: PushHinweis verschickt einen Hinweis, KalenderFeed schreibt den Kalendereintrag. Weitere Beobachter wie ein Chat-Hinweis müssen nur Observer realisieren; Aktivitaet bleibt unverändert (lose Kopplung, Erweiterbarkeit).

  1. Erläutere die Art der Beziehung zwischen Aktivitaet und Observer und begründe, warum hier keine Komposition vorliegt. (3 Punkte)

Erläuterung (2 Punkte): Aggregation, eine Ganzes-Teile- bzw. „hat ein“-Beziehung: Eine Aktivität hält in ihrer Liste observers beliebig viele (auch keine) angemeldete Beobachter. Die Beziehung führt zum Interface, nicht zu den konkreten Klassen.

Begründung (1 Punkt): Die Beobachter existieren unabhängig von der Aktivität. Sie werden außerhalb erzeugt, melden sich an und ab und können mehrere Aktivitäten zugleich beobachten. Wird eine Aktivität gelöscht, müssen ihre Beobachter nicht mit gelöscht werden. Bei einer Komposition wären die Teile existenzabhängig vom Ganzen und gehörten nur zu genau einem Ganzen.

  1. Implementiere die Methoden addObserver, removeObserver und notifyObservers der Klasse Aktivitaet in Pseudocode. (5 Punkte)

Prozedur addObserver(o: Observer)
    observers.hinzufuegen(o)
Ende addObserver

Prozedur removeObserver(o: Observer)
    observers.entfernen(o)
Ende removeObserver

Prozedur notifyObservers()
    für jedes o in observers
        o.update()
    Ende für
Ende notifyObservers

Bewertung: addObserver 1 Punkt, removeObserver 1 Punkt (je 0,5 Methodenkopf, 0,5 Hinzufügen bzw. Entfernen); notifyObservers 3 Punkte (0,5 Methodenkopf, 1,5 Schleife über alle Beobachter als For-each-Schleife oder als Zählschleife von Index 0 bis Anzahl − 1, 1 Aufruf update() am jeweiligen Element).

  1. Der Konstruktor von PushHinweis speichert die übergebene Aktivität in seinem Attribut und meldet das neue Objekt bei dieser Aktivität als Beobachter an. Gib den Konstruktor in Pseudocode an. (3 Punkte)

Konstruktor PushHinweis(a: Aktivitaet)
    this.aktivitaet := a
    a.addObserver(this)
Ende PushHinweis

Bewertung: 1 Punkt Zuweisung der Referenz an das Attribut, 2 Punkte Anmeldung mit addObserver am übergebenen Objekt und Übergabe des eigenen Objekts mit this (in Pseudo-Python self). Der Methodenkopf ist vorgegeben; ohne ihn kein Abzug.

  1. Die Methode update() der Klasse PushHinweis erzeugt einen Hinweistext und verschickt ihn mit sende(text) an die Teilnehmenden. Ist die Aktivität abgesagt (Status "abgesagt"), lautet der Text <Titel> wurde abgesagt., sonst <Titel>: neuer Beginn <Beginn>. Implementiere die Methode in Pseudocode. (4 Punkte)

Prozedur update()
    text: string := aktivitaet.getTitel()
    wenn aktivitaet.getStatus() = "abgesagt" dann
        text := text & " wurde abgesagt."
    sonst
        text := text & ": neuer Beginn " & aktivitaet.getBeginn()
    Ende wenn
    sende(text)
Ende update

Bewertung: 1 Punkt Abruf der Daten über Getter an der gespeicherten Referenz aktivitaet (Pull-Modell), 1 Punkt Bedingung über den Status, 1 Punkt beide Texte, 1 Punkt Aufruf sende(text).

Beispiel: Wird der „Fotospaziergang Sparrenburg“ vom 31.10.2026 auf 16:00 Uhr verschoben, lautet der Text „Fotospaziergang Sparrenburg: neuer Beginn 31.10.2026 16:00“.

Sabine Hoffmann, die den Fotospaziergang an der Sparrenburg organisiert, verschiebt den Beginn vom 31.10.2026 um 15:30 Uhr auf 16:00 Uhr, damit mehr Teilnehmende das Herbstlicht nutzen können. Für die Dokumentation soll dieser Ablauf exemplarisch mit einem Beobachter dargestellt werden:

  • Der Client erzeugt das Aktivitaet-Objekt akt und das PushHinweis-Objekt push, dem akt übergeben wird (bereits dargestellt).

  • Im Konstruktor von push wird die Methode addObserver aufgerufen.

  • Der Client ruft die Methode verschieben mit dem neuen Beginn auf.

  • In verschieben wird der neue Beginn gespeichert und anschließend notifyObservers gestartet.

  • notifyObservers ruft für jeden angemeldeten Beobachter update auf. Stelle die Wiederholung dar, auch wenn hier nur ein Beobachter angemeldet ist.

  • update holt sich wie in Teilaufgabe i) Titel, Status und Beginn und ruft sende auf.

  • Der Kontrollfluss geht von sende über update, notifyObservers und verschieben zurück zum Client.

Vorgabe: Sequenzdiagramm mit Client, akt :Aktivitaet und push :PushHinweis; nur die beiden Erzeugungsnachrichten sind eingezeichnet (mit KI erstellt)
  1. Ergänze das UML-Sequenzdiagramm gemäß der Ablaufbeschreibung um alle fehlenden Nachrichten, Antworten und Aktivierungsbalken mit Beschriftung. (11 Punkte)
Lösung: Anmeldung im Konstruktor, verschieben mit Selbstaufruf notifyObservers, Schleife mit update, Rückrufe getTitel, getStatus und getBeginn, Selbstaufruf sende und Rückweg zum Client (mit KI erstellt)

Bewertung (11 Punkte):

  • je Nachricht mit zugehöriger Antwort und richtiger Beschriftung 1 Punkt: addObserver(push), verschieben(…), notifyObservers(), update(), getTitel(), getStatus(), getBeginn(), sende(text) (8 Punkte); Rückgabewerte an den Getter-Antworten sind erwünscht

  • loop-Fragment mit Bedingung um update() und die Rückrufe (1 Punkt)

  • Aktivierungsbalken: Konstruktor von push bis zur Rückkehr an den Client, geschachtelte Balken für die Selbstaufrufe notifyObservers() und sende(text), kurze Balken auf akt für die Getter (2 Punkte)

Typische Fehler: addObserver geht vom Client statt vom Beobachter aus; die Getter werden von akt an push geschickt (Richtung vertauscht); Antworten fehlen; der Rückweg endet nicht beim Client.

Jonas Weber, Dein Mit-Azubi, hat eine erste Fassung zweier Methoden programmiert. Beim Test zeigt der Push-Hinweis den alten Beginn an, und das Programm bricht mit einem Indexfehler ab.

Prozedur verschieben(neuerBeginn: DateTime)
    notifyObservers()
    beginn := neuerBeginn
Ende verschieben

Prozedur notifyObservers()
    zähle i von 0 bis laenge(observers)
        Observer.update()
    Ende zähle
Ende notifyObservers
  1. Analysiere den Code. Beschreibe die drei Fehler und gib eine korrigierte Fassung beider Methoden an. (6 Punkte)

Je Fehler 1 Punkt Beschreibung, 1 Punkt Korrektur:

  1. Reihenfolge in verschieben (Zeilen 2 und 3): Die Beobachter werden benachrichtigt, bevor der neue Beginn gespeichert ist. Sie holen sich in update() noch den alten Wert. Erst ändern, dann benachrichtigen.

  2. Schleifengrenze (Zeile 7): Mit Index ab 0 ist die Anzahl der Beobachter minus 1 der letzte gültige Index. Die Schleife läuft einen Durchlauf zu weit bis zur Anzahl selbst und greift auf ein nicht vorhandenes Element zu (Indexfehler).

  3. Aufruf am Interface (Zeile 8): Observer.update() ruft die Methode am Interface-Typ auf, nicht am jeweiligen Beobachter-Objekt. Richtig ist der Aufruf am Element der Liste: observers[i].update().

Prozedur verschieben(neuerBeginn: DateTime)
    beginn := neuerBeginn
    notifyObservers()
Ende verschieben

Prozedur notifyObservers()
    zähle i von 0 bis laenge(observers) - 1
        observers[i].update()
    Ende zähle
Ende notifyObservers

Eine For-each-Schleife, die für jedes Element o der Liste o.update() aufruft (wie in Teilaufgabe g), ist ebenfalls richtig und vermeidet den Grenzfehler.

Aufgabe 3.2: Fertigungsfortschritt im Fahrrad-Onlineshop (Profilkompetenz)

(ca. 36 min Bearbeitungszeit)

Du bist Auszubildende*r im Entwicklungsteam der CSB-Rad GmbH in Bielefeld. Rahmen nach Maß fertigt der Partner Rahmenwerk OWL in Gütersloh. Dessen Fertigungssteuerung (MES) meldet jede Statusänderung eines Fertigungsauftrags an das Shop-Backend: uebermittelt, in_produktion, qualitaetspruefung, versandbereit, geliefert oder fehler.

Chiamaka Okafor-Schmidt hat ein Lastenrad „Long John“ mit Rahmen nach Maß bestellt; der zugehörige MES-Auftrag hat die Nummer 1041 und steht gerade auf in_produktion. Sie soll den Fortschritt in ihrem Kundenkonto sehen. Zugleich braucht Werkstattleiter Bastian Ludwig einen Werkstattplan: Sobald ein Rahmen versandbereit ist, kommt er auf die Montageliste für die kommende Woche.

Cem Sarıkaya, Geschäftsführer Technik und IT, möchte das Beobachter-Muster nutzen. Weil später auch Bestellungen und Sendungen ihren Status melden sollen, gibt er eine abstrakte Klasse StatusQuelle vor, die die Verwaltung der Beobachter für alle Statusquellen übernimmt. Die Beobachter heißen in diesem Projekt Listener.

  1. Nenne die Kategorie von Entwurfsmustern, zu der das Beobachter-Muster gehört, und ein weiteres Muster dieser Kategorie. (2 Punkte)

Verhaltensmuster (behavioral pattern) (1 Punkt). Weitere Verhaltensmuster (1 Punkt), z. B. Strategie, Zustand, Schablonenmethode, Befehl (Command), Iterator.

Der Entwurf sieht bisher so aus:

Vorgabe: abstrakte Klasse StatusQuelle, Interface StatusListener, Klassen Fertigungsauftrag, Kundenkonto und Werkstattplan ohne Beziehungen und mit Lücken in den Methoden (mit KI erstellt)
  1. Vervollständige das Klassendiagramm. Zeichne alle Beziehungen zwischen den Klassen ein – bei der Beziehung zwischen StatusQuelle und StatusListener mit Multiplizitäten – und ergänze die fehlenden Methoden in Fertigungsauftrag, Kundenkonto und Werkstattplan. (8 Punkte)
Lösung: Fertigungsauftrag erbt von StatusQuelle, StatusQuelle aggregiert beliebig viele StatusListener, Kundenkonto und Werkstattplan realisieren StatusListener; ergänzte Methoden (mit KI erstellt)

Bewertung (8 Punkte):

  • Generalisierung Fertigungsauftrag → StatusQuelle (durchgezogen, hohles Dreieck an StatusQuelle): 1 Punkt

  • Aggregation StatusQuelle (Raute) – StatusListener mit 0..* an beiden Enden (an der StatusQuelle ist auch 1 vertretbar): 2 Punkte

  • Realisierungen Kundenkonto und Werkstattplan → StatusListener (gestrichelt, hohles Dreieck): je 1 Punkt (2 Punkte)

  • Fertigungsauftrag: Überschreiben der drei abstrakten Methoden +setStatus(neuerStatus: String), +getStatus(): String, +getBezeichnung(): String: je 0,5 Punkte (1,5 Punkte)

  • Kundenkonto und Werkstattplan: je +statusGeaendert(q: StatusQuelle): je 0,75 Punkte (1,5 Punkte)

Hinweis: addListener, removeListener und informiereListener werden nicht in Fertigungsauftrag wiederholt. Sie sind in der Oberklasse bereits implementiert und werden geerbt.

  1. Erläutere den Unterschied zwischen der Beziehung Fertigungsauftrag – StatusQuelle und der Beziehung Kundenkonto – StatusListener. (4 Punkte)
  • Fertigungsauftrag – StatusQuelle: Generalisierung/Vererbung (2 Punkte). Ein Fertigungsauftrag „ist eine“ Statusquelle. Er erbt das Attribut listener und die fertig implementierten Methoden addListener, removeListener und informiereListener und muss nur die abstrakten Methoden überschreiben. Von der abstrakten Klasse selbst können keine Objekte erzeugt werden.

  • Kundenkonto – StatusListener: Realisierung (2 Punkte). StatusListener ist ein Interface ohne Implementierung. Kundenkonto verpflichtet sich, die Methode statusGeaendert selbst zu implementieren, und kann dadurch überall eingesetzt werden, wo ein StatusListener erwartet wird. Es erbt keinen Code. Eine Klasse kann viele Interfaces realisieren, aber (in Java) nur von einer Klasse erben.

  1. Im Entwurf ist informiereListener() geschützt (#) und setStatus(…) abstrakt. Begründe beide Festlegungen. (3 Punkte)
  • #informiereListener() (1,5 Punkte): Nur die Statusquelle selbst und ihre Unterklassen sollen die Listener informieren – genau dann, wenn sich ihr Status tatsächlich geändert hat. Fremde Klassen sollen keine Benachrichtigungen ohne Änderung auslösen können. Unterklassen wie Fertigungsauftrag müssen die Methode aber aufrufen können; deshalb protected und nicht private.

  • setStatus(…) abstrakt (1,5 Punkte): Jede Art von Statusquelle (Fertigungsauftrag, später Bestellung oder Sendung) hat eigene Statuswerte und eigene Regeln für eine Statusänderung. Die abstrakte Oberklasse legt nur fest, dass es die Methode gibt, und zwingt jede Unterklasse, sie zu implementieren. Eine Unterklasse, die sie nicht überschreibt, ist selbst abstrakt; von ihr können keine Objekte erzeugt werden.

  1. Implementiere die Methode setStatus(neuerStatus : String) der Klasse Fertigungsauftrag in Pseudocode. Die Listener sollen nur informiert werden, wenn sich der Status tatsächlich ändert. (3 Punkte)

Prozedur setStatus(neuerStatus: string)
    wenn neuerStatus <> status dann
        status := neuerStatus
        informiereListener()
    Ende wenn
Ende setStatus

Bewertung: 1 Punkt Bedingung (Vergleich mit dem bisherigen Status), 1 Punkt Zuweisung, 1 Punkt Aufruf von informiereListener() nach der Zuweisung.

  1. Die Methode informiereListener() der Klasse StatusQuelle ruft bei jedem angemeldeten Listener statusGeaendert auf und übergibt dabei die Statusquelle selbst. Implementiere die Methode in Pseudocode mit einer Zählschleife. (3 Punkte)

geschützt Prozedur informiereListener()
    zähle i von 0 bis laenge(listener) - 1
        listener[i].statusGeaendert(this)
    Ende zähle
Ende informiereListener

Bewertung: 0,5 Punkte Methodenkopf, 1 Punkt Zählschleife mit richtigen Grenzen, 1 Punkt Aufruf am jeweiligen Element, 0,5 Punkte Übergabe der eigenen Instanz mit this (in Pseudo-Python self).

  1. Implementiere die Methode statusGeaendert(q : StatusQuelle) der Klasse Werkstattplan in Pseudocode. Ist der neue Status versandbereit, wird die Bezeichnung der Statusquelle (z. B. „Fertigungsauftrag 1041“) in die Montageliste aufgenommen. Ist er fehler, wird die Bezeichnung – falls vorhanden – wieder aus der Montageliste entfernt. (4 Punkte)

Prozedur statusGeaendert(q: StatusQuelle)
    status: string := q.getStatus()
    wenn status = "versandbereit" dann
        montageliste.hinzufuegen(q.getBezeichnung())
    sonst wenn status = "fehler" dann
        wenn montageliste.enthaelt(q.getBezeichnung()) dann
            montageliste.entfernen(q.getBezeichnung())
        Ende wenn
    Ende wenn
Ende statusGeaendert

Bewertung: 1 Punkt Abfrage des Status über die übergebene Referenz q, 1 Punkt Fall versandbereit mit Hinzufügen, 1 Punkt Fall fehler mit Entfernen, 1 Punkt Verwendung von getBezeichnung() und schlüssige Kontrollstruktur. Die Prüfung, ob die Bezeichnung in der Montageliste enthalten ist, ist erwünscht, aber nicht zwingend, wenn entfernen bei fehlendem Element nichts tut.

Jonas, Dein Mit-Azubi, findet den Rückruf über q umständlich. Er schlägt vor, die Methode in statusGeaendert(auftragNr, status, kundenname, email, lieferadresse) zu ändern, „damit jeder Listener gleich alles bekommt“. Später soll auch ein Listener KundenMail dazukommen.

  1. Erläutere den Unterschied zwischen Push- und Pull-Modell beim Beobachter-Muster und nimm Stellung zu Jonas’ Vorschlag. (4 Punkte)

Erläuterung (2 Punkte):

  • Pull-Modell: Das Subjekt teilt nur mit, dass sich etwas geändert hat (update() bzw. hier statusGeaendert(q) mit der Quelle). Jeder Beobachter holt sich über Getter selbst die Daten, die er braucht.

  • Push-Modell: Das Subjekt schickt die geänderten Daten als Parameter gleich mit. Die Beobachter müssen nicht zurückfragen.

Der Entwurf ist eine Mischform: Übergeben wird die Quelle, die Daten werden per Pull geholt.

Stellungnahme (2 Punkte), z. B.: Jonas’ Vorschlag ist abzulehnen. Kundenname, E-Mail-Adresse und Lieferadresse sind personenbezogene Daten. Beim Push gingen sie an alle Listener, auch an den Werkstattplan, der sie nicht braucht – das widerspricht der Datenminimierung (Art. 5 Abs. 1 lit. c DSGVO). Außerdem müsste bei jedem neuen Datum die Schnittstelle aller Listener geändert werden, und StatusListener passt dann nicht mehr für Bestellungen oder Sendungen mit anderen Daten. Besser: beim Pull bleiben und KundenMail die nötigen Kontaktdaten selbst über die Bestellung abrufen lassen. Andere begründete Stellungnahmen (z. B. ein schmaler Push nur mit auftragNr und status) sind ebenfalls richtig.

  1. Uwe Brinkmann, stellvertretender Lagerleiter, fragt, warum die Werkstattplan-Software nicht einfach alle 30 Sekunden in der Datenbank nachsieht, ob sich ein Status geändert hat. Begründe mit zwei Argumenten, warum das Beobachter-Muster hier besser geeignet ist. (3 Punkte)

1,5 Punkte je Argument, z. B.:

  • Aktualität: Beim Beobachter wird der Werkstattplan sofort bei der Statusänderung informiert. Beim regelmäßigen Nachfragen (Polling) vergehen bis zu 30 Sekunden.

  • Last: Polling fragt auch dann ständig nach, wenn sich nichts geändert hat – bei vielen Aufträgen und mehreren Anzeigen unnötige Datenbankabfragen. Der Beobachter arbeitet nur bei tatsächlichen Änderungen.

  • Einheitlicher Ablauf und Erweiterbarkeit: Alle Interessenten (Kundenkonto, Werkstattplan, später KundenMail) werden auf dieselbe Weise informiert; neue Listener kommen ohne eigene Abfragelogik hinzu.

Das Kundenkonto wird nach dem Model-View-Controller-Muster (MVC) umgesetzt. Chiamaka Okafor-Schmidt möchte die Auslieferung ihres Lastenrads auf einen späteren Wunschtermin verschieben und klickt dazu im Kundenkonto auf „Wunschtermin speichern“. Die folgenden Aktivitäten laufen dabei ab (nicht in der richtigen Reihenfolge):

Aktivitäten im MVC-Muster (ungeordnet)
Buchstabe Aktivität
A Das Model informiert die View über die Zustandsänderung.
B Die View informiert den Controller über die Benutzereingabe.
C Die View fordert die geänderten Daten zur Anzeige beim Model an.
D Der Controller fordert das Model auf, seinen Zustand zu ändern.
  1. Gib die richtige Reihenfolge der Aktivitäten an und nenne, welche Rolle im MVC-Muster die Klasse Kundenkonto übernimmt und welche Rolle das Objekt, das Chiamakas Auftrag verwaltet. (4 Punkte)

Reihenfolge (3 Punkte, je richtiger Position 0,75 Punkte):

Lösung: Reihenfolge im MVC-Muster
Schritt Buchstabe Aktivität
1 B Die View informiert den Controller über die Benutzereingabe.
2 D Der Controller fordert das Model auf, seinen Zustand zu ändern.
3 A Das Model informiert die View über die Zustandsänderung.
4 C Die View fordert die geänderten Daten zur Anzeige beim Model an.

Rollen (1 Punkt): Kundenkonto ist die View (Beobachter); das Objekt mit den Auftragsdaten – hier der Fertigungsauftrag bzw. die Bestellung – ist das Model (Subjekt). Schritt 3 und 4 sind genau das Beobachter-Muster im Pull-Modell.

Das Frontend-Team möchte das Kundenkonto mit einem Web-Framework umsetzen, das Datenbindung (data binding) unterstützt.

  1. Erläutere den Begriff Datenbindung. (2 Punkte)

Bei der Datenbindung wird eine Eigenschaft eines Datenobjekts mit einem Element der Benutzeroberfläche verknüpft (1 Punkt). Ändert sich der Wert im Datenobjekt (z. B. der Fertigungsstatus), zeigt das Oberflächenelement ihn automatisch an; bei einer Zwei-Wege-Bindung gelangen Eingaben (z. B. der Wunschtermin) auch automatisch zurück ins Datenobjekt (1 Punkt). Das Framework übernimmt dabei die Benachrichtigung, die sonst mit dem Beobachter-Muster selbst programmiert wird.


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zum Entwurfsmuster Beobachter (Observer)” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/entwurfsmuster-observer-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/design-pattern/entwurfsmuster. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 28.10.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: