logo

Factory-Methode Design Pattern

Das Factory Method Design Pattern ist ein kreatives Designmuster Dies stellt eine Schnittstelle zum Erstellen von Objekten in einer Oberklasse bereit und ermöglicht es Unterklassen, den Typ der zu erstellenden Objekte zu ändern. Es kapselt die Objekterstellungslogik in einer separaten Methode und fördert so eine lose Kopplung zwischen dem Ersteller und den erstellten Objekten. Dieses Muster ist besonders nützlich, wenn die genauen Typen der zu erstellenden Objekte variieren können oder zur Laufzeit bestimmt werden müssen, was Flexibilität und Erweiterbarkeit bei der Objekterstellung ermöglicht.

Inhaltsverzeichnis



Was ist das Factory Method Design Pattern?

Das Factory Method Design Pattern ist ein kreatives Designmuster, das in der Softwareentwicklung verwendet wird, um eine Schnittstelle zum Erstellen von Objekten in einer Oberklasse bereitzustellen und es gleichzeitig Unterklassen zu ermöglichen, den Typ der zu erstellenden Objekte zu ändern. Es kapselt die Objekterstellungslogik in einer separaten Methode, abstrahiert den Instanziierungsprozess und fördert eine lose Kopplung zwischen dem Ersteller und den erstellten Objekten. Dieses Muster ermöglicht Flexibilität, Erweiterbarkeit und Wartbarkeit in der Codebasis, indem es Unterklassen ermöglicht, ihre eigene Implementierung der Factory-Methode zu definieren, um bestimmte Objekttypen zu erstellen.

foreach-Schleifen-Typoskript

Wann sollte das Factory Method Design Pattern verwendet werden?

Verwenden Sie das Entwurfsmuster der Factory-Methode:

  • Wenn Sie die Objekterstellung kapseln möchten: Wenn Sie über einen komplexen Objekterstellungsprozess verfügen oder der Prozess je nach Bedingungen variieren kann, kann die Kapselung dieser Logik in einer Factory-Methode den Clientcode vereinfachen und die Wiederverwendbarkeit fördern.
  • Wenn Sie Clientcode von konkreten Klassen entkoppeln möchten: Mithilfe des Factory-Methodenmusters können Sie Objekte über eine Schnittstelle oder eine abstrakte Klasse erstellen und dabei die spezifischen Implementierungsdetails der konkreten Klassen vom Clientcode abstrahieren. Dies fördert eine lose Kopplung und macht es einfacher, das System zu ändern oder zu erweitern, ohne den vorhandenen Client-Code zu beeinträchtigen.
  • Wenn Sie mehrere Produktvarianten unterstützen müssen: Wenn Ihre Anwendung verschiedene Variationen eines Produkts erstellen muss oder wenn in Zukunft möglicherweise neue Produkttypen eingeführt werden, bietet das Factory Method Pattern eine flexible Möglichkeit, diese Variationen zu berücksichtigen, indem Factory-Methoden für jeden Produkttyp definiert werden.
  • Wenn Sie die Anpassung oder Konfiguration unterstützen möchten: Fabriken können verwendet werden, um Konfigurationslogik zu kapseln, sodass Clients den Erstellungsprozess anpassen können, indem sie der Factory-Methode Parameter oder Konfigurationsoptionen bereitstellen.

Komponenten des Factory-Methodenentwurfsmusters

1. Schöpfer

Dies ist eine abstrakte Klasse oder eine Schnittstelle, die die Factory-Methode deklariert. Der Ersteller enthält normalerweise eine Methode, die als Factory zum Erstellen von Objekten dient. Es kann auch andere Methoden enthalten, die mit den erstellten Objekten arbeiten.

2. Konkreter Schöpfer

Konkrete Creator-Klassen sind Unterklassen des Creators, die die Factory-Methode implementieren, um bestimmte Objekttypen zu erstellen. Jeder Betonschöpfer ist für die Herstellung eines bestimmten Produkts verantwortlich.

3. Produkt

Dies ist die Schnittstelle oder abstrakte Klasse für die Objekte, die die Factory-Methode erstellt. Das Produkt definiert die gemeinsame Schnittstelle für alle Objekte, die die Factory-Methode erstellen kann.

4. Betonprodukt

Konkrete Produktklassen sind die tatsächlichen Objekte, die die Factory-Methode erstellt. Jede konkrete Produktklasse implementiert die Produktschnittstelle oder erweitert die abstrakte Produktklasse.

Beispiel für ein Factory-Methodenentwurfsmuster

Nachfolgend finden Sie die Problemstellung zum Verständnis des Factory Method Design Pattern:

String als int umwandeln

Stellen Sie sich eine Softwareanwendung vor, die die Erstellung verschiedener Fahrzeugtypen wie Zweiräder, Dreiräder und Vierräder bewältigen muss. Jeder Fahrzeugtyp hat seine eigenen spezifischen Eigenschaften und Verhaltensweisen.

1. Ohne Factory Method Design Pattern

Java
/*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Client (or user) class class Client {  private Vehicle pVehicle;  public Client(int type) {  if (type == 1) {  pVehicle = new TwoWheeler();  } else if (type == 2) {  pVehicle = new FourWheeler();  } else {  pVehicle = null;  }  }  public void cleanup() {  if (pVehicle != null) {  pVehicle = null;  }  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  Client pClient = new Client(1);  Vehicle pVehicle = pClient.getVehicle();  if (pVehicle != null) {  pVehicle.printVehicle();  }  pClient.cleanup();  } }>
Ausgabe
I am two wheeler>

Was sind die Probleme mit dem oben genannten Design?

Im obigen Codedesign:

  • Enge Kopplung: Die Client-KlasseClient>instanziiert direkt die konkreten Klassen (TwoWheeler>UndFourWheeler>) basierend auf dem Eingabetyp, der während der Erstellung bereitgestellt wurde. Dies führt zu einer engen Kopplung zwischen dem Client und den konkreten Klassen, was die Wartung und Erweiterung des Codes erschwert.
  • Verstoß gegen das Single-Responsibility-Prinzip (SRP): DerClient>Die Klasse ist nicht nur dafür verantwortlich, anhand des Eingabetyps zu bestimmen, welcher Fahrzeugtyp instanziiert werden soll, sondern auch für die Verwaltung des Lebenszyklus des Fahrzeugobjekts (z. B. Bereinigung). Dies verstößt gegen das Single-Responsibility-Prinzip, das besagt, dass eine Klasse nur einen Grund für eine Änderung haben sollte.
  • Begrenzte Skalierbarkeit: Das Hinzufügen eines neuen Fahrzeugtyps erfordert eine ÄnderungClient>Klasse, die gegen das Open-Closed-Prinzip verstößt. Dieses Design ist nicht skalierbar, da es nicht an neue Fahrzeugtypen angepasst werden kann, ohne den vorhandenen Code zu ändern.

Wie vermeiden wir das Problem?

  • Factory-Schnittstelle definieren: Ein ... kreierenVehicleFactory>Schnittstelle oder abstrakte Klasse mit einer Methode zum Erstellen von Fahrzeugen.
  • Betonfabriken implementieren: Implementieren Sie konkrete Fabrikklassen (TwoWheelerFactory>UndFourWheelerFactory>), die die implementierenVehicleFactory>Schnittstelle und Bereitstellung von Methoden zum Erstellen von Instanzen bestimmter Fahrzeugtypen.
  • Refactor-Client: Modifiziere denClient>Klasse, um a zu akzeptierenVehicleFactory>Instanz statt Fahrzeuge direkt zu instanziieren. Der Kunde fordert ein Fahrzeug vom Werk an, sodass keine bedingte Logik basierend auf Fahrzeugtypen erforderlich ist.
  • Erhöhte Flexibilität: Mit diesem Ansatz ist das Hinzufügen neuer Fahrzeugtypen so einfach wie das Erstellen einer neuen Fabrikklasse für den neuen Fahrzeugtyp, ohne den vorhandenen Clientcode zu ändern.

2. Mit Factory Method Design Pattern

Teilen wir den Code in komponentenweise Code auf:

FactoryMethodDesignPattern

1. Produktschnittstelle

Java
// Product interface representing a vehicle public abstract class Vehicle {  public abstract void printVehicle(); }>

2. Betonprodukte

Java
// Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } public class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } }>

3. Creator-Schnittstelle (Werksschnittstelle)

Java
// Factory interface defining the factory method public interface VehicleFactory {  Vehicle createVehicle(); }>

4. Betonschöpfer (Betonfabriken)

Java
// Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } }>

Vollständiger Code dieses Beispiels:

Java
// Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Factory Interface interface VehicleFactory {  Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } } // Client class class Client {  private Vehicle pVehicle;  public Client(VehicleFactory factory) {  pVehicle = factory.createVehicle();  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  VehicleFactory twoWheelerFactory = new TwoWheelerFactory();  Client twoWheelerClient = new Client(twoWheelerFactory);  Vehicle twoWheeler = twoWheelerClient.getVehicle();  twoWheeler.printVehicle();  VehicleFactory fourWheelerFactory = new FourWheelerFactory();  Client fourWheelerClient = new Client(fourWheelerFactory);  Vehicle fourWheeler = fourWheelerClient.getVehicle();  fourWheeler.printVehicle();  } }>
Ausgabe
I am two wheeler I am four wheeler>

Im obigen Code:

Wählen Sie SQL aus mehreren Tabellen aus
  • Vehicle> dient als Produktschnittstelle und definiert die gemeinsame Methode printVehicle()> die alle konkreten Produkte umsetzen müssen.
  • TwoWheeler> Und FourWheeler> sind konkrete Produktklassen, die verschiedene Fahrzeugtypen repräsentieren und die implementieren printVehicle()> Methode.
  • VehicleFactory> fungiert als Creator-Schnittstelle (Factory Interface) mit einer Methode createVehicle()> repräsentiert die Factory-Methode.
  • TwoWheelerFactory> Und FourWheelerFactory> sind konkrete Erstellerklassen (Concrete Factories), die das implementieren VehicleFactory> Schnittstelle zum Erstellen von Instanzen bestimmter Fahrzeugtypen.

Anwendungsfälle des Factory-Methodenentwurfsmusters

Hier sind einige häufige Anwendungen des Factory Method Design-Musters:

  • Kreationsrahmen:
    • JDBC (Java Database Connectivity) nutzt Factorys in großem Umfang zum Erstellen von Verbindungen, Anweisungen und Ergebnismengen. Dependency-Injection-Frameworks wie Spring und Guice verlassen sich bei der Erstellung und Verwaltung von Beans stark auf Fabriken.
  • GUI-Toolkits:
    • Swing und JavaFX verwenden Fabriken, um UI-Komponenten wie Schaltflächen, Textfelder und Beschriftungen zu erstellen, was eine individuelle Anpassung und Flexibilität beim UI-Design ermöglicht.
  • Protokollierungs-Frameworks:
    • Protokollierungsframeworks wie Log4j und Logback verwenden Fabriken, um Logger mit unterschiedlichen Konfigurationen zu erstellen und so die Kontrolle über Protokollierungsstufen und Ausgabeziele zu ermöglichen.
  • Serialisierung und Deserialisierung:
    • Objektserialisierungs-Frameworks verwenden häufig Fabriken, um Objekte aus serialisierten Daten zu erstellen, und unterstützen dabei verschiedene Serialisierungsformate und Versionierung.
  • Plugin-Systeme:
    • Plugin-basierte Systeme verwenden häufig Fabriken, um Plugin-Instanzen dynamisch zu laden und zu erstellen und so Erweiterbarkeit und Anpassung zu ermöglichen.
  • Spieleentwicklung:
    • Spiel-Engines verwenden häufig Fabriken, um verschiedene Arten von Spielobjekten, Charakteren und Levels zu erstellen und so die Organisation und Flexibilität des Codes zu fördern.
  • Web Entwicklung:
    • Web-Frameworks verwenden manchmal Fabriken, um Ansichtskomponenten, Controller und Dienste zu erstellen und so Modularität und Testbarkeit in Webanwendungen zu ermöglichen.

Vorteile des Factory Method Design Patterns

Die Vorteile des Factory Method Design Pattern sind:

Java-String-Join
  • Entkopplung: Es trennt die Objekterstellungslogik vom Clientcode, der diese Objekte verwendet. Dadurch wird der Code flexibler und wartbarer, da Änderungen am Erstellungsprozess keine Änderungen am Client-Code erfordern.
  • Erweiterbarkeit: Es ist einfach, neue Produkttypen einzuführen, ohne den Client-Code zu ändern. Sie müssen lediglich eine neue Concrete Creator-Unterklasse erstellen und die Factory-Methode implementieren, um das neue Produkt herzustellen.
  • Testbarkeit: Es vereinfacht Unit-Tests, indem es Ihnen ermöglicht, die Produkterstellung während der Tests zu simulieren oder auszublenden. Sie können verschiedene Produktimplementierungen isoliert testen, ohne sich auf die tatsächliche Objekterstellung verlassen zu müssen.
  • Wiederverwendbarkeit des Codes: Die Factory-Methode kann in verschiedenen Teilen der Anwendung wiederverwendet werden, in denen eine Objekterstellung erforderlich ist. Dies fördert die Zentralisierung und Wiederverwendung der Objekterstellungslogik.
  • Verkapselung: Es verbirgt die konkreten Produktklassen vor dem Client-Code, wodurch der Code weniger von bestimmten Implementierungen abhängig wird. Dies verbessert die Wartbarkeit und reduziert die Kopplung.

Nachteile des Factory-Methodenentwurfsmusters

Die Nachteile des Factory Method Design Pattern sind:

  • Erhöhte Komplexität: Es führt zusätzliche Klassen und Schnittstellen ein und fügt eine Abstraktionsebene hinzu, die das Verständnis und die Wartung des Codes komplexer machen kann, insbesondere für diejenigen, die mit dem Muster nicht vertraut sind.
  • Gemeinkosten: Die Verwendung von Polymorphismus und dynamischer Bindung kann sich leicht auf die Leistung auswirken, obwohl dies in den meisten Anwendungen oft vernachlässigbar ist.
  • Enge Kopplung innerhalb der Produkthierarchien: Betonschöpfer sind immer noch eng mit ihren entsprechenden Betonprodukten verbunden. Änderungen an dem einen erfordern oft Änderungen am anderen.
  • Abhängigkeit von konkreten Unterklassen: Der Client-Code hängt immer noch von der abstrakten Creator-Klasse ab und erfordert Kenntnisse über ihre konkreten Unterklassen, um korrekte Factory-Methodenaufrufe durchzuführen.
  • Potenzial für Überbeanspruchung: Es ist wichtig, das Factory-Methodenmuster mit Bedacht einzusetzen, um eine Überentwicklung der Anwendung zu vermeiden. Die einfache Objekterstellung kann oft direkt durchgeführt werden, ohne dass eine Factory erforderlich ist.
  • Herausforderungen beim Testen: Das Testen der Fabriklogik selbst kann komplexer sein.