Schnellschnapper

Du bekommst den Auftrag ein Reaktionsspiel für zwei Spieler zu programmieren. Für das Spiel werden drei Gegenstände auf einem Tisch plaziert. Dann wird in zufälligen Abständen eine zufällige Zahl zwischen eins und drei erzeugt. Die Zahl wird angezeigt und beide Spieler müssen versuchen den entsprechenden Gegenstand zu schnappen. Wer den Gegenstand geschnappt hat, hat das Spiel gewonnen. Das Spiel kann auch mit einer vorher festgelegten Zahl an Runden gespielt werden.

Der Auftraggeber spielt mit dem Gedanken das Spiel nicht nur für PC's, sondern auch für andere Systeme wie z.B. Handies oder Spielekonsolen zu vermarkten. Deshalb ist es unabdingbar die Klasse, welche die Zufallszahl erzeugt - und vom System unabhängig ist - von der GUI - die systemabhängig ist - zu trennen. (Was man ja eigentlich sowieso immer machen sollte)

Aufgabe - Implementierung der Zufallszahl-Klasse

Schreibe eine Klasse, deren Objekte in zufälligen Abständen eine zufällige Zahl erzeugen. Zum Testen kannst Du die Zahlen auf dem Bildschirm ausgeben lassen.

Das Problem ist aber dann: Woher weiß die GUI wann eine neue Zahl erzeugt wurde?

Observer-Pattern

Das Observer Pattern kann benutzt werden, wenn Objekte (Beobachter) vom Zustand eines anderen Objekts (Subjekt) abhängig sind und über dessen Zustandsänderung informiert werden sollen.

Dazu melden sich beliebig viele Beobachter beim Subjekt an, damit das Subjekt weiß wen es im Falle einer Änderung benachrichtigen muss. Sobald sich etwas am Zustand des Subjekts geändert hat, werden alle Beobachter darüber informiert. Bei Bedarf können die Beobachter dann den genauen Zustand des Subjekts erfragen.

UML-Diagramm

Implementierung

Subjekt: Zur Verwaltung der Beobachter muss je eine Referenz auf jeden Beobachter gespeichert werden. Dazu bietet sich z.B. eine ArrayList an. Beim Anmelden eines Beobachters wird dieser dann in der ArrayList gespeichert, beim Abmelden wird dieser aus der Liste entfernt. Das Subjekt muss auch die Fähigkeit besitzen alle Beobachter zu benachrichtigen, wenn sich etwas am Zustand geändert hat. Dazu wird für jeden Beobachter des Subjekts dessen aktualisieren()-Methode aufgerufen.

KonkretesSubjekt: Meistens müssen die Beobachter weitere Informationen erfragen, sobald sie wissen, dass sich etwas am Zustand des Subjekts geändert hat. Dazu müssen entsprechende get-Methoden implementiert sein.

Beobachter: Das Interface fordert nur die Implementierung einer aktualisieren()-Methode.

KonkreterBeobachter: Implementiert das Interface Beobachter und reagiert auf die Benachrichtigungen des Subjekts, wenn sich dessen Zustand geändert hat.

Schnellschnapper mit Oberver-Pattern

Aufgabe - Das fertige Spiel

Erstelle das UML-Diagramm für das "Schnellschnapper"-Spiel und implementiere es. Passe dazu die oben programmierte Klasse an und ergänze die noch fehlenden Klassen. Beachte dabei die nachfolgenden Tipps.

Tipps:

  • Das UML-Diagramm sieht im Prinzip so aus wie das allgemeine Diagramm. Die Klassennamen werden natürlich durch sinnvolle Namen ersetzt. Außerdem müssen weitere Methoden hinzugefügt werden. So muss das Spiel z.B. gestartet werden und die aktuelle Zahl erfragt werden können.
  • Der KonkreteBeobachter kann entweder textbasiert sein oder eine GUI. Bei einer textbasierten Version wird die Änderung des Zustands über System.out.println(...) ausgegeben. Bei einer GUI-Version kann dies z.B. über ein Label erfolgen.
  • Man muss sich überlegen wie das Spiel erzeugt und gestartet wird. Hier gibt es mehrere Möglichkeiten:
    • Die von der Programmierung einfachste, aber vom Start des Spiels aufwändigste Variante wäre die Objekte in BlueJ zu erzeugen und dann alle Methoden zur Initialisierung und zum Start per Hand aufzurufen.
    • Eine andere Möglichkeit wäre eine weitere, fünfte Klasse zu schreiben, die dann alle anderen Objekte erzeugt und initialisiert. Ein Objekt der erzeugenden Klasse wird dann über public static void main(...) gestartet.
    • Eine weitere Möglichkeit wäre, dass in der GUI das Objekt, das die Spielfunktionalität enthält, erzeugt wird. Die GUI wird dann über public static void main(...) gestartet.

Aufgabe - Alternative GUI

Um den Auftraggeber davon zu überzeugen wie einfach sich die GUI nun austauschen lässt, soll eine zweite Variante der GUI - z.B. grafisch oder textorientiert - geschrieben werden. DO IT!

Weitere Übungsaufgaben

Aufgabe - GUIs und Observer

Auch bei GUI's findet das Observer-Pattern Anwendung.

Erstelle eine einfache GUI mit BlueJ, bei der ein Button benutzt wird. Beim Klicken auf den Button soll z.B. ein Text auf dem Bildschirm ausgegeben werden oder ein Label seinen Text ändern.
Beschreibe (in Stichworten) Gemeinsamkeiten und Unterschiede zum oben beschriebenen Observer-Pattern. Erstelle dazu auch ein UML-Diagramm, das u.a. Deine GUI-Klasse und die Button-Klasse enthält.

Aufgabe - Wetterstation

Es soll eine virtuelle Wetterstation erstellt werden. Diese aktualisiert in regelmäßigen Abständen ihre Messdaten. Es soll verschiedene Anzeigen geben (die sich aber z.B. über System.out.println(..) die Konsole teilen dürfen). Eine Anzeige stellt alle verfügbaren Daten dar, eine andere Anzeige stellt Maximum und Minimum-Werte z.B. der letzten 10 Messdaten dar. Wieder eine andere Anzeige gibt einen Alarm aus, wenn die Temperatur über oder unter einen festgesetzten Wert fällt.

Entwirf ein Klassendiagramm wie es Dir für die Anwendung sinnvoll erscheint, es muss nicht unbedingt das Observer-Muster in starrer Form genutzt werden. Entscheide Dich begründet für eine Push oder Pull-Variante, um die Daten der Wetterstation an die Beobachter zu leiten.

Implementiere das System und starte die Wetterstation.