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.
Aufgabe
EinfachLassen 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 namensShape, das als gemeinsamer Vertrag für alle Formen dient. Ihr Interface sollte eine einzige Methodedraw()deklarieren, die nichts zurückgibt, aber Informationen über die gezeichnete Form ausgibt.Shapes.java: Erstellen Sie drei Klassen, die IhrShape-Interface implementieren:Circle- seinedraw()-Methode sollteDrawing a CircleausgebenRectangle- seinedraw()-Methode sollteDrawing a RectangleausgebenTriangle- seinedraw()-Methode sollteDrawing a TriangleausgebenShapeFactory.java: Erstellen Sie die Factory-Klasse, die die Erstellung der Formen übernimmt. IhreShapeFactorysollte eine statische MethodecreateShape(String type)haben, die einShapezurückgibt. Basierend auf dem Parameter type:- Wenn type gleich
"circle"ist, geben Sie ein neuesCircle-Objekt zurück - Wenn type gleich
"rectangle"ist, geben Sie ein neuesRectangle-Objekt zurück - Wenn type gleich
"triangle"ist, geben Sie ein neuesTriangle-Objekt zurück - Für jeden anderen Wert geben Sie
nullzurück
- Wenn type gleich
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 einerShape-Variablen zu speichern. Wenn die Factory eine gültige Form zurückgibt (nicht null), rufen Sie derendraw()-Methode auf. Wenn sie null zurückgibt, geben SieUnknown 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
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenFelder (Attribute)Konstruktor-MethodeKonstruktor-ÜberladungRückblick – Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (extends)Das super-SchlüsselwortMethoden überschreiben (@Override)Konstruktor-VerkettungDie Object-KlasseEinfache & mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-InterfaceZusammenfassung – Benutzerdefiniertes Sortieren2Zugriffsmodifikatoren & Kapselung
Überblick über ZugriffsebenenGetter- und Setter-MethodenInformation HidingDas final-SchlüsselwortRückblick – Bankkonto-Manager5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenZusammenfassung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, geschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Teil 1
Einführung in Design PatternsSingleton-PatternFactory-PatternBuilder-PatternObserver-PatternStrategy-Pattern14Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung3Klasseneigenschaften & Statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Zusammenfassung – Zähler & Utility6Interfaces & Abstrakte Klassen
Einführung in InterfacesInterfaces implementierenImplementierung mehrerer InterfacesDefault- & statische Methoden in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesZusammenfassung - Zahlungssystem