Menu
Coddy logo textTech

Factory-Pattern

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 66 von 87.

Das Factory Pattern ist ein Erzeugungsmuster, das die Objekterstellung an eine separate Methode oder Klasse delegiert. Anstatt new direkt in Ihrem Code zu verwenden, bitten Sie eine Factory, Objekte für Sie zu erstellen. Dies ist besonders nützlich, wenn Sie mehrere verwandte Klassen haben, die eine gemeinsame Schnittstelle oder Elternklasse teilen.

Stellen Sie sich ein Benachrichtigungssystem vor, das E-Mails, SMS oder Push-Benachrichtigungen senden kann. Ohne eine Factory müsste Ihr Code jede konkrete Klasse kennen:

// Ohne Factory - der Client muss alle konkreten Klassen kennen
Notification notification;
if (type.equals("email")) {
    notification = new EmailNotification();
} else if (type.equals("sms")) {
    notification = new SMSNotification();
}

Mit dem Factory-Pattern zentralisieren Sie diese Erstellungslogik:

public interface Notification {
    void send(String message);
}

public class EmailNotification implements Notification {
    public void send(String message) {
        System.out.println("Email: " + message);
    }
}

public class SMSNotification implements Notification {
    public void send(String message) {
        System.out.println("SMS: " + message);
    }
}

public class NotificationFactory {
    public static Notification create(String type) {
        if (type.equals("email")) {
            return new EmailNotification();
        } else if (type.equals("sms")) {
            return new SMSNotification();
        }
        return null;
    }
}

Jetzt ist der Client-Code sauberer und hängt nicht von konkreten Klassen ab:

Notification notification = NotificationFactory.create("email");
notification.send("Hello!");  // Ausgabe: Email: Hello!

Der entscheidende Vorteil besteht darin, dass das Hinzufügen neuer Benachrichtigungstypen lediglich eine Aktualisierung der Factory erfordert – der Client-Code bleibt unverändert. Dies folgt dem Prinzip der Programmierung gegen eine Schnittstelle, wodurch Ihr System flexibler und einfacher zu erweitern ist.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Form-Zeichensystem mit dem Factory Pattern erstellen! Anstatt Form-Objekte direkt in Ihrem gesamten Code zu erstellen, zentralisieren Sie die Erstellungslogik in einer Factory, die verschiedene Arten von Formen basierend auf einer einfachen String-Kennung erzeugt.

Sie werden Ihren Code über vier Dateien organisieren:

  • Shape.java: Definieren Sie ein Interface namens Shape, das als gemeinsamer Vertrag für alle Formen dient. Ihr Interface sollte eine einzige Methode draw() deklarieren, die nichts zurückgibt, aber Informationen über die gezeichnete Form ausgibt.
  • Shapes.java: Erstellen Sie drei Klassen, die Ihr Shape-Interface implementieren:

    Circle - seine draw()-Methode sollte Drawing a Circle ausgeben

    Rectangle - seine draw()-Methode sollte Drawing a Rectangle ausgeben

    Triangle - seine draw()-Methode sollte Drawing a Triangle ausgeben

  • ShapeFactory.java: Erstellen Sie die Factory-Klasse, die die Erstellung der Formen übernimmt. Ihre ShapeFactory sollte eine statische Methode createShape(String type) haben, die ein Shape zurückgibt. Basierend auf dem Parameter type:
    • Wenn type gleich "circle" ist, geben Sie ein neues Circle-Objekt zurück
    • Wenn type gleich "rectangle" ist, geben Sie ein neues Rectangle-Objekt zurück
    • Wenn type gleich "triangle" ist, geben Sie ein neues Triangle-Objekt zurück
    • Für jeden anderen Wert geben Sie null zurück
  • Main.java: Führen Sie Ihr Factory-System zusammen! Sie erhalten zwei Eingaben: zwei Formtypen (beides Strings).

    Verwenden Sie für jede Eingabe Ihre ShapeFactory, um die Form zu erstellen und in einer Shape-Variablen zu speichern. Wenn die Factory eine gültige Form zurückgibt (nicht null), rufen Sie deren draw()-Methode auf. Wenn sie null zurückgibt, geben Sie Unknown shape: [type] aus, wobei [type] die bereitgestellte Eingabe ist.

    Verarbeiten Sie beide Eingaben nacheinander, jede in einer eigenen Zeile der Ausgabe.

Sie erhalten zwei Eingaben nacheinander: den ersten Formtyp (String) und den zweiten Formtyp (String).

Beachten Sie, dass Ihre Main-Klasse niemals new Circle() oder new Rectangle() direkt verwendet — sie kennt nur das Shape-Interface und bittet die Factory, Objekte zu erstellen. Dies ist die Stärke des Factory Patterns: Der Client-Code ist von den konkreten Klassen entkoppelt!

Spickzettel

Das Factory Pattern (Fabrikmuster) ist ein Erzeugungsmuster, das die Objekterstellung an eine separate Methode oder Klasse delegiert, wodurch die Erstellungslogik zentralisiert und der Client-Code von konkreten Implementierungen entkoppelt wird.

Anstatt Objekte direkt mit new zu instanziieren, verwenden Sie eine Factory-Methode:

// Ohne Factory - Client hängt von konkreten Klassen ab
Notification notification;
if (type.equals("email")) {
    notification = new EmailNotification();
} else if (type.equals("sms")) {
    notification = new SMSNotification();
}

Definieren Sie beim Factory Pattern ein gemeinsames Interface und konkrete Implementierungen:

public interface Notification {
    void send(String message);
}

public class EmailNotification implements Notification {
    public void send(String message) {
        System.out.println("Email: " + message);
    }
}

public class SMSNotification implements Notification {
    public void send(String message) {
        System.out.println("SMS: " + message);
    }
}

Erstellen Sie eine Factory-Klasse mit einer statischen Erstellungsmethode:

public class NotificationFactory {
    public static Notification create(String type) {
        if (type.equals("email")) {
            return new EmailNotification();
        } else if (type.equals("sms")) {
            return new SMSNotification();
        }
        return null;
    }
}

Der Client-Code verwendet die Factory anstelle der direkten Instanziierung:

Notification notification = NotificationFactory.create("email");
notification.send("Hello!");  // Ausgabe: Email: Hello!

Vorteile: Das Hinzufügen neuer Typen erfordert nur die Aktualisierung der Factory – der Client-Code bleibt unverändert. Dies folgt dem Prinzip der Programmierung gegen ein Interface, was Systeme flexibler und einfacher erweiterbar macht.

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Lies zwei Formtypen ein
        String type1 = scanner.nextLine();
        String type2 = scanner.nextLine();
        
        // TODO: Verwende ShapeFactory, um die erste Form zu erstellen
        // Wenn die Form nicht null ist, rufe draw() auf
        // Wenn die Form null ist, gib "Unknown shape: [type]" aus
        
        // TODO: Mache dasselbe für die zweite Form
        
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung