Aufgabe

Werbung
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
U08 Entwurfsmuster (II)
Inhalt der Übung
¾ Diskussion und Implementierung von Entwurfsmustern
Übungsaufgaben
Aufgabe 1 (Queue)
Gegeben ist das folgende Analysemodell einer Warteschlange (Queue):
Eine Warteschlange (Queue) besteht aus einer geordneten Reihenfolge von Objekten
(Object). Objekte werden nach dem FIFO-Prinzip („first-in, first out“) in eine
Warteschlange als letztes Element aufgenommen (add()) und als erstes Element
entfernt (remove()).
front() stellt das erste Element der Warteschlange bereit.
isEmpty() testet, ob die Warteschlange leer ist.
size() ermittelt die Anzahl der Objekte in der Warteschlange.
Es können zwei Arten von Warteschlangen erzeugt werden (siehe Klassendiagramm
unten):
¾ Warteschlangen ohne duplizierte Objekte (d.h., ein Objekt kann sich nur genau
einmal in der Warteschlange „anstellen“ Æ withDuplicates = false)
¾ Warteschlangen mit duplizierten Objekten (d.h., ein Objekt kann sich mehrfach in
der Warteschlange „anstellen“ Æ withDuplicates = true)
Dementsprechend wird zur Implementation entweder
¾ eine Liste ohne duplizierte Objekte („geordnete Menge“ Æ OrderedSet, nicht
im Java-Collection-Framework enthalten, erbt von java.util.List und
java.util.Set ) oder
¾ eine „herkömmliche“ Liste (hier java.util.LinkedList) benutzt.
Seite 1 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Seite 2 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Um die Warteschlange entsprechend dem gegebenen Modell zu implementieren,
brauchen Sie (wie zuvor erklärt) eine geordnete Menge. Da im Java-CollectionFramework eine solche Datenstruktur nicht verfügbar ist, müssen Sie diese zunächst
selbst implementieren (Klasse OrderedSetImpl). Gegeben ist dazu das Interface
OrderedSet.java. Die Erläuterung der Methoden ist im Java-Code von
OrderedSet.java enthalten.
Lösen Sie folgende Teilaufgaben:
¾ Welche Entwurfsmuster sind im Modell berücksichtigt? Diskutieren Sie diese
Entwurfsmuster und zeichnen Sie sie in UML-Notation in das Klassendiagramm
ein!
¾ Implementieren und testen Sie! (Praktomat: Queue)
Hinweise:
o Um die Warteschlange entsprechend dem gegebenen Modell zu
implementieren, brauchen Sie (wie zuvor erklärt) eine geordnete Menge.
Da im Java-Collection-Framework eine solche Datenstruktur nicht
verfügbar ist, müssen Sie diese zunächst selbst implementieren (Klasse
OrderedSetImpl). Gegeben ist dazu das Interface
OrderedSet.java. Die Erläuterung der Methoden ist im Java-Code
von OrderedSet enthalten.
o Jetzt können Sie mit Hilfe der Datenstruktur „geordnete Menge“ eine
Warteschlange implementieren (QueueImpl)! Gegeben ist dazu das
Interface Queue.java.
Seite 3 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Aufgabe 2 (Vehicle Queue)
Gegeben ist ein Entwurfsmodell für die Simulation einer Verkehrs(warte)schlange
(VehicleQueue) an einer (Rot-Grün-)Ampel.
Fahrzeuge (Vehicle) in dieser Schlange können Busse (Bus), Autos (Car) und
Fahrräder (Bicycle) sein. Die Methode createVehicle()der Klasse
VehicleGenerator erzeugt per Zufallsgenerator (randomGenerator)
entweder einen Bus, ein Auto oder ein Fahrrad.
In der Verkehrsschlange stellen sich Fahrzeuge (enter()) mit einer zu definierenden
Häufigkeit pro Sekunde (vehiclesPerSecondEnter) an.
Falls die Ampel auf grün steht (greenLight == true), verlassen Fahrzeuge die
Schlange (leave()) mit einer ebenfalls zu definierenden Häufigkeit
(vehiclesPerSecondLeave). Die Variable trafficLightRate gibt die
Zeitdauer einer Rot- als auch Grünphase der Ampel in Sekunden an. Initialisiert ist die
Ampel mit rot (greenLight == false).
Die Methoden getLength() und getSize() berechnen die Länge der
Verkehrsschlange in Metern bzw. in Anzahl von Fahrzeugen.
Die Zeit wird durch ein Time–Objekt simuliert. Time kennt die aktuelle Zeit in
Sekunden (currentTime) sowie eine Zeitbegrenzung in Sekunden (endOfTime).
Die Methode run() zählt (immer mit 0 beginnend) die Zeit sekundenweise bis zur
Zeitbegrenzung hoch. Der folgende Codeausschnitt aus der Klasse Simulation
demonstriert beispielhaft die Anwendung der Klassen Time und VehicleQueue.
public class Simulation {
static Time myTime . . .
public static void main (String args[]) {
VehicleQueue queue =
new VehicleQueue(0.1, 30, 0.5, new
VehicleGenerator());
. . .
myTime.initEndOfTime(70);
myTime.run();
}
}
Lösen Sie folgende Teilaufgaben:
¾ Überdenken Sie den gegebenen Entwurf der Klasse Time, indem Sie die Klasse zu
einem Singleton verändern. Ergänzen Sie dementsprechend die Klasse im UMLKlassendiagramm!
¾ Implementieren Sie die Klassen VehicleQueue und Time! Nach jeder Sekunde
sollen entsprechend der oben beschriebenen Variablen Fahrzeuge die Schlange
betreten als auch verlassen. Nutzen Sie zur Simulation (Simulation.java) des
Sekundentaktes das Observer-Entwurfsmuster! Gegeben sind die Klassen
Vehicle.java, VehicleGenerator.java, Bus.java,
Bicycle.java und Car.java.
Seite 4 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
¾ Welches weitere Entwurfsmuster (neben Singleton und Observer) ist im Entwurf
enthalten?
¾ Zeichen Sie die Entwurfsmuster in UML-Notation in das nachfolgende
Klassendiagramm ein!
¾ Implementieren Sie das Modell und testen Sie! (Praktomat: Vehicle Queue)!
Seite 5 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Aufgabe 3 (Pricing)
Der folgende Entwurf (siehe Klassendiagramm) modelliert eine komplexe
Preisbildungslogik, die insbesondere verschiedene Rabatte ermöglicht. Grundsätzlich
gibt es zwei Rabattarten:
¾ Prozentualer Rabatt auf den Listenpreis (Klasse
PercentageDiscountPricing).
Der gewährte Prozentsatz percentage wird dem Konstruktor übergeben
(0 <= percentage < 100).
¾ Absoluter Rabatt auf den Listenpreis (Klasse AbsoluteDiscountPricing).
Der absolute Rabatt discount wird nur für den Listenpreis oberhalb eines
Mindesteinkaufspreises (threshold) gewährt. Der Mindesteinkaufspreis darf
auch nach Anwendung eines Rabattes nicht unterschritten werden.
Beide Parameter werden dem Konstruktor übergeben.
Die Klasse Sale berechnet für einen Verkaufsvorgang ausgehend von einem
Listenpreis (preDiscountTotal) den Preis für den Kunden unter Gewährung von
Rabatten (Methode getTotal()). Die eigentliche Rabattberechnung wird von
einem ISalePricing-Objekt vorgenommen, dessen Methode getTotal()
dazu ein Sale-Objekt übergeben wird.
Nun kann es sein, dass gleichzeitig verschiedene Rabatte angewendet werden können
(z.B. Rabatt für Senioren oder andere spezielle Kunden, Treuebonus, Tagesrabatte).
Da Rabatte in unserer Anwendung nicht kumuliert werden können, ist ein Rabatt für
die Preisbildung auszuwählen. Hier kommt eine komplexe Preisbildungslogik (Klasse
ComplexPricing) zur Anwendung. Dabei gibt es zwei Alternativen:
¾ Die Klasse BestForCustomerPricing berechnet den Kundenpreis so, dass
der für den Kunden höchste Rabatt ausgewählt und angewendet wird.
¾ Die Klasse BestForStorePricing berechnet den Kundenpreis so, dass der
für den Verkäufer günstigste Rabatt ausgewählt und angewendet wird.
Bevor für einen Verkaufsvorgang der Kundenpreis berechnet wird, müssen alle für
den Kunden anwendbaren Rabatte ausgewählt und der verwendeten
Preisbildungslogik bekannt gemacht werden. Die Rabatte werden mit der Methode
createPricing() der Klasse Sale ausgewählt. Die Parameter dieser Methode
sind
¾ discountType: Die zulässigen Werte für den prozentualen und den absoluten
Rabatt sind durch das Interface DiscountType definiert.
¾ percentage: Im Fall des prozentualen Rabattes wird damit der zu gewährende
Prozentsatz übergeben. Die beiden restlichen Parameter sollten auf 0 gesetzt
werden.
¾ discount und threshold: Im Fall des absoluten Rabattes beschreiben diese
beiden Parameter wie oben erläutert den zu gewährenden Rabatt. Der Parameter
percentage sollte auf 0 gesetzt werden.
Zum Schluss wird die anzuwendende Preisbildungslogik myPricing
(BestForCustomerPricing oder BestForStorePricing im komplexen
Anwendungsfall) mit der Methode setPricing() festgelegt. Die nachfolgende
Klasse SaleApp.java illustriert die Anwendung dieser Methoden:
Seite 6 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
public class SaleApp implements DiscountType {
public static void main (String[] args) {
Sale sale1 = new Sale(100.0);
ISalePricing p1, p2, p3, p4,p5;
p1 = sale1.createPricing(PERCENTAGEDISCOUNT,10.0,0,0);
p2 = sale1.createPricing(PERCENTAGEDISCOUNT,5.0,0,0);
p3 = sale1.createPricing(ABSOLUTEDISCOUNT,0,5,50);
p4 = sale1.createPricing(ABSOLUTEDISCOUNT,0,30,90);
p5 = sale1.createPricing(ABSOLUTEDISCOUNT,0,19,80);
BestForCustomerPricing p = new BestForCustomerPricing(p1);
p.add(p2);
p.add(p3);
p.add(p4);
p.add(p5);
sale1.setPricing(p);
System.out.println("BestForCustomer Price = " +
sale1.getTotal() + " EUR");
}
}
Lösen Sie folgende Teilaufgaben:
¾
Zeichnen Sie die Ihnen bekannten Entwurfsmuster in UML-Notation in das
Klassendiagramm ein!
¾ Implementieren Sie das Modell und testen Sie! (Praktomat: Pricing)!
Seite 7 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Empfehlung
Implementieren Sie als weitere Praktomatsaufgabe Part Management!
Aufgabe 4 (Desktop Search Engine)
Sie haben den Auftrag, eine erste Version einer primitiven Desktopsuchmaschine
(MyDesk) zu entwickeln. Dabei geht es darum, dass (auf einem Rechner) nicht nur
nach Dateien eines bestimmten Namens gesucht werden kann, sondern auch nach
Dateien mit einem bestimmten Dateiinhalt.
Basierend auf der Annahme, dass üblicherweise viele Suchanfragen hintereinander
gestellt werden, soll nicht für jede Anfrage das Dateisystem neu durchsucht werden
müssen. Stattdessen wird ein Index erstellt. Mit der Registrierung jeder Datei im Index
wird dieser um neue Schlüsselwörter und die dazugehörige Datei erweitert.
Als eine besondere Schwierigkeit stellt sich dabei heraus, dass der Inhalt einer Datei
natürlich sehr stark von ihrem Dateityp abhängt. Ein Textdokument beispielsweise
bietet sehr viel Information, die sich gut aufbereiten lässt; bei einer Grafik sieht das
ganz anders aus. Hier ist es im Allgemeinen nicht möglich, passende Schlüsselworte
abzuleiten.
Seite 8 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Für einen ersten Entwurf lassen sich folgende Klassen bzw. Interfaces identifizieren
(siehe Klassendiagramm):
¾ Von zentraler Bedeutung ist die Klasse Resource. Sie stellt eine konkrete Datei
im Index dar. Dazu soll der Dateiname gespeichert werden (name), der Pfad zu
der Datei (path), und ein Verweis auf einen passenden Datei- bzw.
Ressourcentyp (rt).
¾ Der Typ einer Datei wird durch die Klasse ResourceType dargestellt. Sie hat
nur zwei Attribute. Zum einen speichert sie eine Kurzbeschreibung (desc),
welche den Dateityp knapp beschreibt, z.B. "JPG-Graphik", zum anderen verweist
sie auf einen KeywordCollector (collector).
¾ Das
Interface
KeywordCollector
stellt
eine
Methode
getKeywords()bereit, die für die Indexerstellung gebraucht wird. Sie ermittelt
zu einer Resource die Menge ihrer Schlüsselworte.
¾ Eine Klasse, die das Interface KeywordCollector standardmäßig
implementiert, ist der DefaultCollector. Er soll lediglich den Dateinamen
als Schlüsselwort zurück- geben. Der Sinn dieser Klasse ist es, für Dateien
unbekannten Typs wenigstens den Dateinamen als Schlüsselwort verwenden zu
können.
¾ Die Klasse PlainTextCollector als weitere Implementierung von
KeywordCollector berechnet mit Hilfe des TextFileIterators zu einer
Textdatei die Menge der in ihr enthaltenen Worte als Schlüsselworte. Dazu
wandelt der TextFileIterator den gesamten Inhalt einer Textdatei in einen
String um (getAsString()). Der TextFileIterator implementiert das
Interface java.util.Iterator. Er soll nacheinander alle Wörter der
Textdatei zurückliefern. Wörter werden durch alle Zeichen voneinander getrennt,
die nicht Buchstaben oder Ziffern sind. Als zusätzliche Besonderheit sollen
getrennte Wörter erkannt und wieder zusammengefügt werden. Eine Worttrennung
liegt dann vor, wenn auf die Zeichensequenz Bindestrich/Zeilenumbruch („-\n“)
direkt ein Kleinbuchstabe folgt.
¾ Die Klasse MyDesc schließlich stellt die Funktionalität zur Verfügung, die für die
Desktopsuchmaschine gebraucht wird. Dazu gehört neben der Registrierung eines
neuen Dateityps (registerType()) das Hinzufügen einer Datei zum Index
(registerResource())
und
das
Bearbeiten
einer
Suchanfrage
(processRequest()).
¾ Der Index der auf dem Desktop registrierten Dateien wird in der Klasse Index
verwaltet. Er stellt eine Abbildung von Schlüsselwörtern auf Dateien dar (pro
Schlüsselwort eine Liste von Dateien). Die zu einer Datei gehörigen
Schlüsselwörter wurden über den zugehörigen KeywordCollector ermittelt.
Es ist möglich, eine Datei in den Index aufzunehmen (add()) und sich die Liste
von Dateien geben zu lassen, die mit einem bestimmten Schlüsselwort indiziert
sind (getResources()).
Seite 9 von 10
Dr. Birgit Demuth, Lehrstuhl Softwaretechnologie, LV Softwaretechnologie, WS 2007/08
Lösen Sie folgende Aufgaben:
a) Welche (zwei) Entwurfsmuster erkennen Sie in dem Modell? Zeichnen Sie diese
in das Klassendiagramm ein! Ergänzen Sie dazu das Modell um ggf. fehlende
Klassen/Interfaces.
b) Implementieren und testen Sie (Praktomat: Desktop Search Engine).
Seite 10 von 10
Herunterladen