Die Paketstation
AFB I–IIEin Logistikunternehmen betreibt Paketstationen mit je 24 Fächern. Jedes Paket ist für genau einen Kunden bestimmt. Ein Kunde kann mehrere Pakete in derselben Station liegen haben. Die Software ist bereits in Teilen modelliert.
- - standort: Zeichenkette
- - faecher: Reihung von Paket
- c Paketstation(standort: Zeichenkette)
- + einlegen(fach: Ganzzahl, p: Paket)
- + abholen(k: Kunde): Ganzzahl
- - sendungsnummer: Zeichenkette
- - empfaenger: Kunde
- c Paket(nr: Zeichenkette, k: Kunde)
- + getEmpfaenger(): Kunde
- - name: Zeichenkette
- c Kunde(name: Zeichenkette)
- + getName(): Zeichenkette
- Beschreiben Sie die im Klassendiagramm dargestellten Beziehungen. Gehen Sie dabei auf Navigationsrichtung und Kardinalitäten ein. 4 BE
- Implementieren Sie die Methode
abholen(k: Kunde): Ganzzahlder KlassePaketstation. Sie entnimmt alle Pakete, deren Empfängerkist (die Fächer werden frei), und liefert die Anzahl der entnommenen Pakete. 6 BE - Stellen Sie den Zustand nach den folgenden Anweisungen in einem Objektdiagramm dar. Beschränken Sie sich bei der Station auf die belegten Fächer.
Kunde ina = new Kunde("Ina"); Kunde tom = new Kunde("Tom"); Paketstation st = new Paketstation("Bahnhof"); st.einlegen(0, new Paket("A1", ina)); st.einlegen(3, new Paket("B7", tom)); st.einlegen(5, new Paket("C2", ina));Geben Sie außerdem die Rückgabewerte vonst.abholen(ina)an, wenn diese Methode zweimal hintereinander aufgerufen wird. 5 BE - Erläutern Sie, welche Änderungen nötig sind, wenn ein Kunde jederzeit alle für ihn eingelagerten Pakete kennen soll, und welches neue Risiko dadurch entsteht. 4 BE
Summe: 19 BE
Hinweise
Hinweis zu Aufgabe a)
Hinweis zu Aufgabe b)
null — erst prüfen, dann getEmpfaenger() aufrufen. Objekte vergleicht man hier mit ==: gemeint ist genau dieses Kunden-Objekt.Hinweis zu Aufgabe c)
Hinweis zu Aufgabe d)
Erwartungshorizont
Erwartungshorizont zu Aufgabe a)
Eine Paketstation kennt über die Rolle faecher höchstens 24 Pakete (0..24, also auch keins); umgesetzt als Reihung der Länge 24, freie Fächer sind null. Ein Paket kennt über empfaenger genau einen Kunden (1, nie null, im Konstruktor gesetzt). Beide Assoziationen sind nur in Pfeilrichtung navigierbar: Ein Paket weiß nicht, in welcher Station es liegt, ein Kunde kennt seine Pakete nicht.
Erwartungshorizont zu Aufgabe b)
public int abholen(Kunde k) {
int anzahl = 0;
for (int i = 0; i < faecher.length; i++) {
if (faecher[i] != null && faecher[i].getEmpfaenger() == k) {
faecher[i] = null;
anzahl++;
}
}
return anzahl;
}Bewertet: Durchlauf über alle 24 Fächer (2 BE), null-Prüfung vor dem Aufruf mit Kurzschlussauswertung (1 BE), Vergleich des Empfängers (1 BE), Fach freigeben und zählen (1 BE), Rückgabe (1 BE). Ein vorzeitiges return beim ersten Treffer ist falsch, weil ein Kunde mehrere Pakete haben kann.
Erwartungshorizont zu Aufgabe c)
- standort = "Bahnhof"
- faecher[0] → p1
- faecher[3] → p2
- faecher[5] → p3
- sendungsnummer = "A1"
- empfaenger → ina
- sendungsnummer = "B7"
- empfaenger → tom
- sendungsnummer = "C2"
- empfaenger → ina
- name = "Ina"
- name = "Tom"
Die Pakete haben keinen Variablennamen im Programm; die Namen p1–p3 dienen nur dem Diagramm. Zwei Pakete verweisen auf dasselbe Objekt ina. Rückgabewerte: erster Aufruf 2 (Fächer 0 und 5 werden frei), zweiter Aufruf 0.
Erwartungshorizont zu Aufgabe d)
Kunde bekommt ein Attribut - pakete: DynArray<Paket> (Kardinalität * an der Paket-Seite), die Assoziation wird in beide Richtungen navigierbar. einlegen muss das Paket zusätzlich beim Empfänger eintragen, abholen es dort wieder entfernen. Risiko: Die Informationen liegen jetzt doppelt vor. Vergisst eine Methode eine der beiden Seiten, widersprechen sich Station und Kunde (Paket gilt beim Kunden als eingelagert, ist aber längst abgeholt). Deshalb sollten nur wenige, gut getestete Methoden beide Seiten gemeinsam ändern.
Sitzplatzreservierung im Zug
AFB II–IIIEine Bahngesellschaft lässt ihre Platzreservierung neu programmieren. Die Anforderungen stehen im Kasten.
(1) Ein Zug besteht aus mindestens einem Wagen; Wagen können angehängt werden. (2) Jeder Wagen hat eine Nummer und genau 60 Sitzplätze. (3) Ein Sitzplatz ist frei oder genau einer Reservierung zugeordnet. (4) Eine Reservierung kennt den Namen der reisenden Person und ihren Sitzplatz. (5) Der Zug soll die Zahl seiner freien Sitzplätze angeben können.
- Erstellen Sie ein Klassendiagramm mit den Klassen
Zug,Wagen,SitzplatzundReservierung, das die Anforderungen (1) bis (5) erfüllt. Geben Sie Navigationsrichtungen und Kardinalitäten an. 6 BE - Implementieren Sie die Methode
freiePlaetze(): Ganzzahlder KlasseZug. Gehen Sie davon aus, dass jeder Wagen im Konstruktor alle 60 Sitzplatz-Objekte erzeugt und die MethodengetSitz(i: Ganzzahl): SitzplatzundgetAnzahlSitze(): Ganzzahlanbietet. 5 BE - Analysieren Sie die folgende Methode aus der Klasse
Zug, mit der ein Mitarbeiter eine Reservierung anlegt. Zeigen Sie an einem Ablauf, welches Problem sie verursachen kann.public void reservieren(String name, Wagen w, int i) { Sitzplatz s = w.getSitz(i); Reservierung r = new Reservierung(name, s); }Dabei seiReservierungso implementiert, dass der Konstruktor nurthis.sitz = sitz;ausführt. 4 BE - Beurteilen Sie den Vorschlag, in
Sitzplatzstatt der Referenz auf eine Reservierung nur ein Attribut- belegt: Wahrheitswertzu speichern. 4 BE
Summe: 19 BE
Hinweise
Hinweis zu Aufgabe a)
Hinweis zu Aufgabe b)
ArrayList der Wagen, innen über die Sitze eines Wagens.Hinweis zu Aufgabe c)
Hinweis zu Aufgabe d)
Erwartungshorizont
Erwartungshorizont zu Aufgabe a)
- - wagen: DynArray<Wagen>
- c Zug(erster: Wagen)
- + anhaengen(w: Wagen)
- + freiePlaetze(): Ganzzahl
- - nummer: Ganzzahl
- - sitze: Reihung von Sitzplatz
- c Wagen(nummer: Ganzzahl)
- + getSitz(i: Ganzzahl): Sitzplatz
- + getAnzahlSitze(): Ganzzahl
- - nummer: Ganzzahl
- - reservierung: Reservierung
- + istFrei(): Wahrheitswert
- + setReservierung(r: Reservierung)
- - reisender: Zeichenkette
- - sitz: Sitzplatz
- c Reservierung(name: Zeichenkette, s: Sitzplatz)
(1) „mindestens einem Wagen“ → 1..*, umgesetzt als dynamische Reihung; (2) „genau 60“ → Kardinalität 60, umgesetzt als Reihung der Länge 60; (3) „frei oder genau einer“ → 0..1 an der Reservierungs-Seite; (4) „kennt ihren Sitzplatz“ → 1 an der Sitzplatz-Seite. Weil Sitzplatz und Reservierung sich gegenseitig kennen müssen, ist diese Assoziation in beide Richtungen navigierbar (Linie ohne Pfeilspitzen). Je 1 BE für jede der vier Beziehungen, 2 BE für sinnvolle Attribute und Methoden.
Erwartungshorizont zu Aufgabe b)
public int freiePlaetze() {
int frei = 0;
for (int w = 0; w < wagen.size(); w++) {
Wagen wg = wagen.get(w);
for (int i = 0; i < wg.getAnzahlSitze(); i++) {
if (wg.getSitz(i).istFrei()) {
frei++;
}
}
}
return frei;
}Test: Ein Zug mit zwei Wagen und zwei Reservierungen liefert 118. Bewertet: äußere Schleife mit size()/get (2 BE), innere Schleife (1 BE), Prüfung und Zählen (1 BE), Rückgabe (1 BE).
Erwartungshorizont zu Aufgabe c)
Nach dem Aufruf kennt r den Sitzplatz, der Sitzplatz aber nicht die Reservierung: s.istFrei() liefert weiterhin true. Ablauf: reservieren("Lea", w2, 10), danach reservieren("Max", w2, 10) — beide Aufrufe gelingen, der Platz ist doppelt vergeben, und freiePlaetze() zählt ihn trotzdem als frei. Ursache: Bei einer Assoziation in beide Richtungen wurde nur eine Seite gesetzt. Abhilfe: Im Konstruktor der Reservierung sitz.setReservierung(this); ergänzen und in reservieren vorher s.istFrei() prüfen.
Erwartungshorizont zu Aufgabe d)
Vorteil: einfacher, keine gegenseitigen Referenzen, die konsistent gehalten werden müssen; Anforderung (5) lässt sich damit weiterhin erfüllen. Nachteil: Vom Sitzplatz aus ist nicht mehr feststellbar, wer dort sitzt; beim Stornieren muss man die Reservierung über den Namen suchen, und belegt kann dem Bestand der Reservierungen widersprechen (Datenredundanz auf andere Art). Urteil: Für eine reine Belegungsanzeige genügt der Wahrheitswert; da eine Bahn aber Platzkarten prüfen und stornieren muss, ist die Referenz auf die Reservierung die bessere Modellierung — die Konsistenz sichert man durch eine einzige Methode, die beide Seiten setzt.
