Wrap Up

Die folgende Aufgabe ist ein Wrap Up aus den vorangegangenen Themen. Bearbeiten Sie diese Aufgabe, um Ihr Wissen zu festigen und zu vertiefen. Bitte nutze Sie keine Hilfsmittel, um die Aufgabe zu lösen, auch nicht JAIT. Sie sollten dies in Vorbereitung auf die Prüfung selbst lösen können, ohne fremde Hilfe jeglicher Art.

Projekt: Konferenz-Management-System

Szenario Sie entwickeln ein rein textbasiertes Konsolen-Programm zur Verwaltung einer Fachkonferenz. Folgende Funktionen und Komponenten sollen enthalten sein:

1. Enumerations

  • Role Gruppe aller möglichen Benutzerrollen: Teilnehmer, Vortragender, Organisator.

Lösung anzeigen
public enum Role {
    TEILNEHMER,
    VORTRAGENDER,
    ORGANISATOR
}
  • TicketType Definieren Sie drei Ticketkategorien (Student, Standard, VIP) und hinterlegen Sie für jede einen festen Preis (z. B. 50 €, 100 €, 200 €).

Lösung anzeigen
public enum TicketType {
    STUDENT(50.0),
    STANDARD(100.0),
    VIP(200.0);

    private final double preis;

    TicketType(double preis) {
        this.preis = preis;
    }

    public double getPreis() {
        return preis;
    }
}
  • SessionLevel Drei Schwierigkeitsgrade für Sessions: Beginner, Intermediate, Advanced.

Lösung anzeigen
public enum SessionLevel {
    BEGINNER,
    INTERMEDIATE,
    ADVANCED
}

2. Abstrakte Klassen & Interfaces

  • Abstract Class „Person“

    • Attribute: Vorname, Nachname, Rolle

    • Abstrakte Methode „describe“: Jede Unterklasse liefert eine eigene textuelle Kurzbeschreibung.

    • Konkrete Methode „printName“: Gibt Vor- und Nachname sowie die Rolle formatiert aus (mit printf).

Lösung anzeigen
Person.java
 1public abstract class Person {
 2
 3    private final String vorname;
 4    private final String nachname;
 5    private final Role rolle;
 6
 7    public Person(String vorname, String nachname, Role rolle) {
 8        this.vorname = vorname;
 9        this.nachname = nachname;
10        this.rolle = rolle;
11    }
12
13    public abstract String describe();
14
15    public void printName() {
16        System.out.printf( "%s %s (%s)%n", vorname, nachname, rolle );
17    }
18
19    public String getVorname() {
20        return vorname;
21    }
22
23    public String getNachname() {
24        return nachname;
25    }
26
27    public Role getRolle() {
28        return rolle;
29    }
30}
  • Interface „PaymentService“

    • Methode zur Autorisierung eines Betrags (gibt wahr/falsch zurück)

    • Methode zur Ausführung der Zahlung (liefert eine eindeutige zufällige Transaktionskennung)

      Lösung anzeigen
      PaymentService.java
      1public interface PaymentService {
      2    boolean authorize(double betrag);
      3    String executePayment(double betrag);
      4}
      
    • Drei konkrete Implementierungen:
      • Kreditkarte: genehmigt Zahlungen bis 1000 €.

        Lösung anzeigen
        CreditCardPaymentService.java
         1import java.util.UUID;
         2
         3public class CreditCardPaymentService implements PaymentService {
         4
         5    private static final double MAX_AMOUNT = 1000.0;
         6
         7    @Override public boolean authorize(double betrag) {
         8        return betrag > 0 && betrag <= MAX_AMOUNT;
         9    }
        10
        11    @Override public String executePayment(double betrag) {
        12        if (!authorize(betrag)) {
        13            throw new IllegalArgumentException("Kreditkartenzahlung wurde nicht autorisiert.");
        14        }
        15        return "CREDIT-" + UUID.randomUUID();
        16    }
        17}
        
      • PayPal: genehmigt immer, liefert eindeutige Transaktions-ID.

        Lösung anzeigen
        PayPalPaymentService.java
         1import java.util.UUID;
         2
         3public class PayPalPaymentService implements PaymentService {
         4
         5    @Override
         6    public boolean authorize(double betrag) {
         7        return betrag > 0;
         8    }
         9
        10    @Override
        11    public String executePayment(double betrag) {
        12        if (!authorize(betrag)) {
        13            throw new IllegalArgumentException("Der Zahlungsbetrag muss größer als 0 sein.");
        14        }
        15
        16        return "PAYPAL-" + UUID.randomUUID();
        17    }
        18}
        
      • Bitcoin: genehmigt nur bis 0,02 BTC (Umrechnungskurs 50.000 € pro BTC).

        Lösung anzeigen
        BitcoinPaymentService.java
         1import java.util.UUID;
         2
         3public class BitcoinPaymentService implements PaymentService {
         4
         5    private static final double BTC_TO_EURO_RATE = 50_000.0;
         6    private static final double MAX_BTC_AMOUNT = 0.02;
         7
         8    @Override
         9    public boolean authorize(double betrag) {
        10        if (betrag <= 0) {
        11            return false;
        12        }
        13
        14        double betragInBitcoin = betrag / BTC_TO_EURO_RATE;
        15
        16        return betragInBitcoin <= MAX_BTC_AMOUNT;
        17    }
        18
        19    @Override
        20    public String executePayment(double betrag) {
        21        if (!authorize(betrag)) {
        22            throw new IllegalArgumentException("Bitcoin-Zahlung wurde nicht autorisiert.");
        23        }
        24
        25        return "BTC-" + UUID.randomUUID();
        26    }
        27
        28    public double convertEuroToBitcoin(double euroBetrag) {
        29        return euroBetrag / BTC_TO_EURO_RATE;
        30    }
        31}
        

Tipp

🚩 Verwenden Sie für die Transaktions-ID entweder eine zufällige Zahl oder eine UUID (Java-Klasse java.util.UUID).

3. Generics & Collections

  • Generic Repository
    • Intern eine Liste von Objekten des Typs T

    • Methoden:
      • add(item): void

      • remove(item): boolean

      • get(index): T

      • size(): int

      • findAll(predicate): List – liefert alle Elemente, die das Predicate (Functionales Interface!) erfüllen

Nutzen Sie dieses Repository für die Speicherung von Personen und Sessions (nicht zusammen!).

Lösung anzeigen
Repository.java
 1import java.util.ArrayList;
 2import java.util.List;
 3import java.util.function.Predicate;
 4
 5public class Repository<T> {
 6
 7    private final List<T> items = new ArrayList<>();
 8
 9    public void add(T item) {
10        items.add(item);
11    }
12
13    public boolean remove(T item) {
14        return items.remove(item);
15    }
16
17    public T get(int index) {
18        return items.get(index);
19    }
20
21    public int size() {
22        return items.size();
23    }
24
25    public List<T> findAll(Predicate<T> predicate) {
26        List<T> result = new ArrayList<>();
27
28        for (T item : items) {
29            if (predicate.test(item)) {
30                result.add(item);
31            }
32        }
33
34        return result;
35    }
36}

4. Klassenmodell

  • Attendee (Teilnehmer) Erweiterung von Person mit zusätzlichem Attribut „TicketType“.

Lösung anzeigen
Attendee.java
 1public class Attendee extends Person {
 2
 3    private final TicketType ticketType;
 4
 5    public Attendee(String firstName, String lastName, TicketType ticketType) {
 6        super(firstName, lastName, Role.TEILNEHMER);
 7        this.ticketType = ticketType;
 8    }
 9
10    @Override
11    public void describe() {
12        System.out.printf("%s %s nimmt mit einem %s-Ticket für %.2f € teil.%n",
13                           getFirstName(),
14                           getLastName(),
15                           ticketType,
16                           ticketType.getPreis());
17    }
18
19    public TicketType getTicketType() {
20        return ticketType;
21    }
22}
  • Speaker (Vortragender) Erweiterung von Person mit einer Liste der gehaltenen Sessions.

Lösung anzeigen
Speaker.java
 1import java.util.ArrayList;
 2import java.util.List;
 3
 4public class Speaker extends Person {
 5
 6    private final List<Session> sessions = new ArrayList<>();
 7
 8    public Speaker(String firstName, String lastName) {
 9        super(firstName, lastName, Role.VORTRAGENDER);
10    }
11
12    public void addSession(Session session) {
13        sessions.add(session);
14    }
15
16    public List<Session> getSessions() {
17        return List.copyOf(sessions);
18    }
19
20    @Override
21    public void describe() {
22        System.out.printf("%s %s ist Vortragender und hält %d Session(s).%n",
23                           getFirstName(),
24                           getLastName(),
25                           sessions.size());
26    }
27}
  • Session Enthält Titel, Schwierigkeitsgrad (SessionLevel) und den zugehörigen Speaker. Bietet eine Methode, um Titel, Level und Speaker in einem formatierten Satz auszugeben.

Lösung anzeigen
Session.java
 1public class Session {
 2
 3    private final String title;
 4    private final SessionLevel level;
 5    private final Speaker speaker;
 6
 7    public Session(String title, SessionLevel level, Speaker speaker) {
 8        this.title = title;
 9        this.level = level;
10        this.speaker = speaker;
11
12        speaker.addSession(this);
13    }
14
15    public void printDescription() {
16        System.out.printf("Die Session \"%s\" hat das Level %s und wird von %s %s gehalten.%n",
17                           title,
18                           level,
19                           speaker.getFirstName(),
20                           speaker.getLastName());
21    }
22
23    public String getTitle() {
24        return title;
25    }
26
27    public SessionLevel getLevel() {
28        return level;
29    }
30
31    public Speaker getSpeaker() {
32        return speaker;
33    }
34}

Für alle describe()-Methoden bitte formatierte Ausgabe mit printf verwenden.

  • Conference
    • Verwaltet intern zwei Repositories (generische Sammlungen) für alle Personen und alle Sessions, also jeweils Instanzen Ihres generic Repositories.

    • Methoden:
      1. registerUsers(...) – nimmt beliebig viele Personen-Instanzen entgegen und fügt diese dem Repository hinzu.

      2. addSessions(...) – fügt beliebig viele Session-Objekte hinzu.

      3. filterSessions(predicate) – gibt alle Sessions zurück, die einem übergebenen Filterkriterium (Predicate!) genügen.

      4. totalRevenue() – summiert die Ticketpreise aller registrierten Teilnehmer mittels der Java Stream API auf (Hinweis: Methode sum() verwenden) und gibt den Gesamtumsatz zurück.

Verwenden Sie Variable-Argumente (variable Anzahl Parameter) bei den Methoden registerUsers und addSessions, um beliebig viele Parameter zu akzeptieren.

Lösung anzeigen
Session.java
 1import java.util.List;
 2import java.util.function.Predicate;
 3
 4public class Conference {
 5
 6    private final Repository<Person> personRepository = new Repository<>();
 7
 8    private final Repository<Session> sessionRepository = new Repository<>();
 9
10    public void registerUsers(Person... persons) {
11        for (Person person : persons) {
12            personRepository.add(person);
13        }
14    }
15
16    public void addSessions(Session... sessions) {
17        for (Session session : sessions) {
18            sessionRepository.add(session);
19        }
20    }
21
22    public List<Session> filterSessions(Predicate<Session> predicate) {
23        return sessionRepository.findAll(predicate);
24    }
25
26    public double totalRevenue() {
27        return personRepository
28                .findAll(person -> person instanceof Attendee)
29                .stream()
30                .map(person -> (Attendee) person)
31                .mapToDouble(attendee -> attendee.getTicketType().getPreis())
32                .sum();
33    }
34}

5. Streams & Lambdas & Hauptprogramm

In Ihrem Hauptprogramm (Main-Klasse) sollen Sie die folgenden Schritte durchführen:

  1. Teilnehmer & Speaker anlegen: Erstellen Sie mindestens zwei Teilnehmer und zwei Speaker.

  2. Registrierung: Registrieren Sie mehrere Attendee und Speaker für die Konferenz.

  3. Zahlungsabwicklung: Führen Sie für jeden Teilnehmer (nicht Speaker, diese zahlen nichts!) eine Zahlungsabwicklung durch. Verwenden Sie dazu die PaymentService-Implementierungen und erzeugen Sie z.B. in einer HashMap hierzu Beispielzuordnungen, also z.B.

1ArrayList someList = new ArrayList();
2someList.add("A");
3someList.add("B");
4someList.add(2022);
5for (String toPrint : someList) {
6    System.out.println(toPrint);
7}

Geben Sie den Status der Zahlung (genehmigt/abgelehnt) und die Transaktions-ID aus.

  1. Sessions anlegen & zuordnen: Erstellen Sie mindestens drei Sessions und ordnen Sie diese den Speakern zu. Seien Sie bei der Auswahl der Sessions kreativ. :-)

  2. Sessions hinzufügen: Fügen Sie die Sessions der Konferenz hinzu.

  3. Filterung: Ermitteln Sie alle Sessions vom Level „Advanced“ und geben Sie deren Informationen aus. Nutzen Sie hier die Stream API und Lambda-Ausdrücke.

  4. Gruppierung: Bilden Sie eine Übersicht, in der alle Sessions nach ihrem Level (Beginner, Intermediate, Advanced) in Gruppen abgelegt werden. Nutzen Sie hier die Stream API und Lambda-Ausdrücke.

  5. Umsatzberechnung: Ermitteln Sie den Gesamtumsatz aller verkauften Tickets.

Lösung anzeigen
Main.java
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
Aufgabe A
    Attendee attendee1 = new Attendee("Anna", "Müller",TicketType.STUDENT);

    Attendee attendee2 = new Attendee("Lukas", "Schneider", TicketType.VIP);

    Attendee attendee3 = new Attendee("Sophie", "Wagner", TicketType.STANDARD);

    Speaker speaker1 = new Speaker("Max", "Mustermann");

    Speaker speaker2 = new Speaker("Laura", "Weber");
Aufgabe B
    Conference conference = new Conference();

    conference.registerUsers(
            attendee1,
            attendee2,
            attendee3,
            speaker1,
            speaker2
    );
Aufgabe C
    Map<Attendee, PaymentService> paymentServices = new HashMap<>();

    paymentServices.put(attendee1, new CreditCardPaymentService());

    paymentServices.put(attendee2, new PayPalPaymentService());

    paymentServices.put(attendee3, new BitcoinPaymentService());


    // Zahlungsabwicklung durchführen

    System.out.println("Zahlungsabwicklung:");

    paymentServices.forEach((attendee, paymentService) -> {
        double amount = attendee.getTicketType().getPreis();

        boolean authorized = paymentService.authorize(amount);

        if (authorized) {
            String transactionId = paymentService.executePayment(amount);

            System.out.printf(
                    "%s %s: genehmigt – %.2f € – Transaktions-ID: %s%n",
                    attendee.getFirstName(),
                    attendee.getLastName(),
                    amount,
                    transactionId
            );
        } else {
            System.out.printf(
                    "%s %s: abgelehnt – %.2f €%n",
                    attendee.getFirstName(),
                    attendee.getLastName(),
                    amount
            );
        }
    });
Aufgabe D
    Session session1 = new Session(
            "Java für interplanetare Raumfahrtsysteme",
            SessionLevel.ADVANCED,
            speaker1
    );

    Session session2 = new Session(
            "Künstliche Intelligenz für Einsteiger",
            SessionLevel.BEGINNER,
            speaker2
    );

    Session session3 = new Session(
            "Generics, Streams und Lambdas",
            SessionLevel.INTERMEDIATE,
            speaker1
    );

    Session session4 = new Session(
            "Quantencomputing mit Java",
            SessionLevel.ADVANCED,
            speaker2
    );
Aufgabe E
    conference.addSessions(
            session1,
            session2,
            session3,
            session4
    );

    List<Session> sessions = List.of(
            session1,
            session2,
            session3,
            session4
    );
Aufgabe F
    System.out.println();
    System.out.println("Advanced-Sessions:");

    sessions.stream()
            .filter(session -> session.getLevel() == SessionLevel.ADVANCED)
            .forEach(Session::printDescription);
Aufgabe G
    Map<SessionLevel, List<Session>> sessionsByLevel =
            sessions.stream()
                    .collect(Collectors.groupingBy(Session::getLevel));

    System.out.println();
    System.out.println("Sessions nach Level:");

    sessionsByLevel.forEach((level, sessionList) -> {
        System.out.printf("%n%s:%n", level);

        sessionList.forEach(
                Session::printDescription
        );
    });
Aufgabe H
        double totalRevenue = conference.totalRevenue();

        System.out.printf("%nGesamtumsatz: %.2f €%n", totalRevenue);
    }
}