MINT lernen

Abituraufgaben: Klassendiagramm entwerfen

Zwei Abituraufgaben mit Hinweisen und Erwartungshorizont: aus Anforderungen ein Klassendiagramm entwickeln und einen Entwurf verbessern — Carsharing und Festival.

Dein Fortschritt:
0 / 0 Aufgaben
1

Carsharing

AFB I–II

Ein Carsharing-Anbieter lässt eine Verwaltungssoftware entwickeln. Die Anforderungen stehen im Kasten.

Anforderungen des Carsharing-Anbieters

(1) Der Anbieter betreibt mehrere Stationen; jede Station hat einen Namen. (2) An jeder Station stehen bis zu zehn Fahrzeuge. (3) Jedes Fahrzeug hat ein Kennzeichen und einen Preis pro Minute. (4) Elektroautos sind Fahrzeuge, bei denen zusätzlich der Akkustand in Prozent gespeichert wird. (5) Kunden haben einen Namen und eine Führerscheinnummer. (6) Eine Buchung gehört zu genau einem Kunden und genau einem Fahrzeug und speichert die gefahrenen Minuten; aus ihr lassen sich die Kosten berechnen. (7) Jeder Kunde soll alle seine Buchungen einsehen können.

  1. Erstellen Sie ein Klassendiagramm, das die Anforderungen (1) bis (7) erfüllt. Geben Sie Attribute mit Datentypen, die für (6) und (7) nötigen Methoden sowie alle Beziehungen mit Richtung und Kardinalität an. 7 BE
  2. Erläutern Sie zwei Entwurfsentscheidungen Ihres Diagramms: die Modellierung der Elektroautos und die Verbindung zwischen Buchung und Kunde. 4 BE
  3. Implementieren Sie die Klasse Buchung mit Konstruktor und der Methode kosten(): Fließkommazahl. Der Konstruktor soll dafür sorgen, dass Anforderung (7) erfüllt bleibt. 5 BE
  4. Stellen Sie den Zustand nach den folgenden Anweisungen als Objektdiagramm dar und geben Sie den Rückgabewert von b.kosten() an.
    Kunde k = new Kunde("Jo", "B123");
    EAuto e = new EAuto("H-E 42", 0.30, 80);
    Buchung b = new Buchung(k, e, 45);
    3 BE

Summe: 19 BE

Hinweise

Hinweis zu Aufgabe a)
Gehe Satz für Satz vor und notiere, welches Diagrammelement jeder Satz liefert. Zwei Sätze verlangen ein „Kennen“ in beide Richtungen.
Hinweis zu Aufgabe b)
Welche Alternative zur Vererbung gäbe es, und was würde eine Kundennummer statt einer Referenz bedeuten?
Hinweis zu Aufgabe c)
Die Kosten ergeben sich aus den Minuten und dem Minutenpreis des Fahrzeugs. Für (7) muss der Kunde von der neuen Buchung erfahren.
Hinweis zu Aufgabe d)
Drei Objekte; die Buchung zeigt auf die beiden anderen, der Kunde zurück auf die Buchung.

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)
Anbieter
  • - stationen: DynArray<Station>
stationen*
Station
  • - name: Zeichenkette
  • - fahrzeuge: Reihung von Fahrzeug
fahrzeuge0..10
Fahrzeug
  • - kennzeichen: Zeichenkette
  • - preisProMinute: Fließkommazahl
  • + getPreisProMinute(): Fließkommazahl
Fahrzeug
EAuto
  • - akkustand: Ganzzahl
  • c EAuto(k: Zeichenkette, p: Fließkommazahl, akku: Ganzzahl)
Kunde
  • - name: Zeichenkette
  • - fuehrerscheinNr: Zeichenkette
  • - buchungen: DynArray<Buchung>
  • + hinzufuegen(b: Buchung)
buchungen / kunde1*
Buchung
  • - minuten: Ganzzahl
  • - kunde: Kunde
  • - fahrzeug: Fahrzeug
  • c Buchung(k: Kunde, f: Fahrzeug, min: Ganzzahl)
  • + kosten(): Fließkommazahl
fahrzeug1
Fahrzeug

(1) → Anbieter mit * Stationen; (2) „bis zu zehn“ → 0..10, Reihung der Länge 10; (3) Attribute von Fahrzeug; (4) „sind Fahrzeuge“ → EAuto erbt von Fahrzeug; (5) Attribute von Kunde; (6) Buchung → 1 Kunde, → 1 Fahrzeug, Attribut minuten, Methode kosten(); (7) Kunde → * Buchung, also ist die Beziehung Kunde–Buchung in beide Richtungen navigierbar. Bewertet: sechs Klassen (2 BE), Vererbung (1 BE), fünf Assoziationen mit Kardinalitäten und Richtung (3 BE), Attribute/Methoden (1 BE).

Erwartungshorizont zu Aufgabe b)

Elektroautos: Ein Elektroauto ist ein Fahrzeug und hat alle seine Eigenschaften; nur der Akkustand kommt hinzu. Als Unterklasse erbt EAuto Kennzeichen, Preis und getPreisProMinute(); Stationen und Buchungen können mit dem Typ Fahrzeug arbeiten und nehmen trotzdem Elektroautos auf. Ein Attribut akkustand in Fahrzeug wäre bei Verbrennern sinnlos. Buchung und Kunde: Die Buchung speichert eine Referenz auf das Kunden-Objekt statt Name oder Führerscheinnummer — so ist der Kunde eindeutig und direkt erreichbar. Weil (7) verlangt, dass der Kunde seine Buchungen kennt, gibt es zusätzlich die Rückrichtung; beide Seiten müssen gemeinsam gesetzt werden (siehe c).

Erwartungshorizont zu Aufgabe c)
public class Buchung {
    private Kunde kunde;
    private Fahrzeug fahrzeug;
    private int minuten;

    public Buchung(Kunde kunde, Fahrzeug fahrzeug, int minuten) {
        this.kunde = kunde;
        this.fahrzeug = fahrzeug;
        this.minuten = minuten;
        kunde.hinzufuegen(this);      // Kunde kennt seine Buchungen
    }
    public double kosten() {
        return minuten * fahrzeug.getPreisProMinute();
    }
}

Bewertet: Attribute (1 BE), Konstruktor (1 BE), Eintragen beim Kunden mit this (2 BE), kosten() über die Referenz auf das Fahrzeug (1 BE).

Erwartungshorizont zu Aufgabe d)
k: Kunde
  • name = "Jo"
  • fuehrerscheinNr = "B123"
  • buchungen = [b]
b: Buchung
  • minuten = 45
  • kunde → k
  • fahrzeug → e
e: EAuto
  • kennzeichen = "H-E 42"
  • preisProMinute = 0.3
  • akkustand = 80

Das Elektroauto enthält auch die geerbten Attribute. b.kosten() = 45 · 0,30 = 13,5.

2

Das Festival

AFB II–III

Für ein Musikfestival soll eine Planungs- und Ticketsoftware entstehen. Ein Praktikant hat bereits einen ersten Entwurf erstellt.

Erster Entwurf eines Praktikanten (ohne Methoden)
Festival
  • - name: Zeichenkette
  • - buehnen: DynArray<Buehne>
  • - bandnamen: DynArray<Zeichenkette>
Auftritt
  • - bandname: Zeichenkette
  • - buehnennummer: Ganzzahl
  • - beginn: Zeichenkette
Tagesticket
  • - preis: Fließkommazahl
  • - tag: Zeichenkette
  • - kaeufer: Zeichenkette
Festivalticket
  • - preis: Fließkommazahl
  • - kaeufer: Zeichenkette
Buehne
  • - nummer: Ganzzahl
  • - kapazitaet: Ganzzahl

Anforderungen: Ein Festival hat mehrere Bühnen und viele Auftritte. Jeder Auftritt findet mit genau einer Band auf genau einer Bühne statt; eine Band kann mehrmals auftreten. Tickets gibt es als Tagesticket (für einen Tag) und als Festivalticket; jedes Ticket hat einen Preis und kennt seinen Käufer, eine Person mit Name und E-Mail-Adresse.

  1. Analysieren Sie den Entwurf. Stellen Sie drei Schwächen heraus und begründen Sie jeweils, welche Probleme sie im Programm verursachen. 5 BE
  2. Entwerfen Sie einen überarbeiteten Entwurf als Klassendiagramm, der die Schwächen behebt und alle Anforderungen erfüllt. 6 BE
  3. Implementieren Sie die Methode auftritteVon(b: Band): Ganzzahl der Klasse Festival, die zählt, wie oft die Band b auftritt. Auftritt bietet getBand(): Band an. 4 BE
  4. Erörtern Sie, ob ein Ticket seinen Käufer als Objekt kennen sollte oder ob umgekehrt eine Person ihre Tickets kennen sollte. 4 BE

Summe: 19 BE

Hinweise

Hinweis zu Aufgabe a)
Achte auf Namen statt Referenzen, doppelte Attribute und fehlende Beziehungen.
Hinweis zu Aufgabe b)
Neue Klassen Band, Person und eine Oberklasse für die Tickets.
Hinweis zu Aufgabe c)
Durchlauf über alle Auftritte; verglichen wird das Band-Objekt.
Hinweis zu Aufgabe d)
Wer muss im Programm wen finden? Betrachte Einlasskontrolle und „Meine Tickets“-Ansicht.

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)

(1) Namen statt Referenzen: bandname, buehnennummer, kaeufer sind Zeichenketten bzw. Zahlen. Tippfehler führen zu Bands, die es nicht gibt; ändert eine Band ihren Namen, müssen alle Auftritte geändert werden; weitere Daten der Band sind nicht erreichbar. (2) Doppelte Attribute: preis und kaeufer stehen in beiden Ticketklassen — gemeinsame Methoden müssten doppelt programmiert werden, eine Liste „aller Tickets“ ist nicht möglich. (3) Fehlende Beziehung: Das Festival kennt seine Auftritte nicht, nur eine Liste von Bandnamen; ein Programm kann das Line-up gar nicht durchlaufen. Weitere mögliche Punkte: Käufer als Zeichenkette statt eigener Klasse Person.

Erwartungshorizont zu Aufgabe b)
Festival
  • - name: Zeichenkette
  • - buehnen: DynArray<Buehne>
  • - auftritte: DynArray<Auftritt>
  • + auftritteVon(b: Band): Ganzzahl
auftritte*
Auftritt
  • - beginn: Zeichenkette
  • - band: Band
  • - buehne: Buehne
  • + getBand(): Band
band1
Band
  • - name: Zeichenkette

Außerdem: Festival → * Buehne, Auftritt → 1 Buehne.

Ticket
  • - preis: Fließkommazahl
  • - kaeufer: Person
  • + getPreis(): Fließkommazahl
Tagesticket
  • - tag: Zeichenkette
Festivalticket
Ticket
kaeufer1
Person
  • - name: Zeichenkette
  • - email: Zeichenkette

Bewertet: Band und Person als Klassen mit Referenzen (2 BE), Oberklasse Ticket mit Vererbung (2 BE), Assoziationen mit Kardinalitäten 1 und * (2 BE).

Erwartungshorizont zu Aufgabe c)
public int auftritteVon(Band b) {
    int anzahl = 0;
    for (int i = 0; i < auftritte.size(); i++) {
        if (auftritte.get(i).getBand() == b) {
            anzahl++;
        }
    }
    return anzahl;
}

Test: Tritt die Band „Echo“ an zwei von drei geplanten Auftritten auf, liefert die Methode 2. Der Vergleich mit == ist hier richtig, weil es für jede Band genau ein Objekt gibt.

Erwartungshorizont zu Aufgabe d)

Ticket kennt Person: Bei der Einlasskontrolle wird ein Ticket gescannt und der Name des Käufers mit dem Ausweis verglichen — dafür muss man vom Ticket zur Person navigieren. Die Anforderung „kennt seinen Käufer“ verlangt genau diese Richtung. Person kennt Tickets: Sinnvoll für eine Ansicht „Meine Tickets“ oder zum Stornieren, sonst müsste man alle Tickets durchsuchen. Beides zusammen macht die Beziehung bidirektional und erfordert, dass beim Kauf beide Seiten gesetzt werden. Fazit: Pflicht ist die Richtung Ticket → Person; die Gegenrichtung nur, wenn eine Funktion sie wirklich braucht — jede zusätzliche Richtung ist eine Fehlerquelle. Aus Datenschutzsicht spricht für Sparsamkeit zudem, dass eine Person-Klasse mit allen Tickets ein vollständiges Kaufprofil darstellt.