Das Factory Method Pattern ist eines der wichtigsten und häufig verwendeten Entwurfsmuster in der objektorientierten Softwareentwicklung. Es gehört zu den sogenannten kreativen Entwurfsmustern, die sich mit der Instanziierung von Objekten beschäftigen. Dabei ist das Hauptziel des Factory Method Patterns, die Erstellung von Objekten zu kapseln, sodass der genaue Typ des zu erstellenden Objekts zur Laufzeit entschieden werden kann, ohne dass der Client-Code explizit wissen muss, welche Klasse instanziiert wird. Genauso fördert es Flexibilität und Erweiterbarkeit, da der Code nicht direkt an konkrete Implementierungen gebunden ist, sondern vielmehr an Abstraktionen.
Was ist das Factory Method Pattern?
Das Factory Method Pattern stellt eine Methode bereit, die die Erzeugung von Objekten einer bestimmten Familie übernimmt, ohne dass der genaue Typ des Objekts im Code festgelegt wird. Statt direkt ein Objekt einer Klasse zu erzeugen, delegiert der Code die Erstellung an eine sogenannte „Factory“-Methode. Diese Methode entscheidet dann, welches konkrete Objekt basierend auf den Eingaben oder den Bedingungen zur Laufzeit erzeugt wird.
Ferner steht im Kern des Factory Method Patterns also die Entkopplung der Instanziierung von Objekten vom restlichen Code. Entsprechend ermöglicht das Muster es, neue Objekttypen hinzuzufügen, ohne dass der Client-Code geändert werden muss. Stattdessen muss lediglich die Factory-Methode angepasst oder erweitert werden.
Grundstruktur des Factory Method Patterns
Das Factory Method Pattern besteht aus einer abstrakten Klasse oder Schnittstelle, die die Factory-Methode definiert. Konkrete Unterklassen implementieren diese Methode, um spezifische Objekte zu erstellen.
Die Grundstruktur sieht in etwa so aus:
- Creator (oder Factory): Diese abstrakte Klasse oder Schnittstelle deklariert die Factory-Methode, die Objekte erstellt. Sie kann auch eine Standardimplementierung für diese Methode enthalten, die von den Subklassen überschrieben werden kann.
- ConcreteCreator (oder konkrete Factory): Diese Klasse implementiert die Factory-Methode, um konkrete Produktobjekte zu erstellen.
- Product: Das Produkt ist das Objekt, das von der Factory-Methode erzeugt wird.
- ConcreteProduct: Die konkrete Implementierung des Produkts.
Beispiel des Factory Method Patterns in C++
Um das Factory Method Pattern in C++ zu veranschaulichen, betrachten wir ein Beispiel, in dem verschiedene Arten von „Fahrzeugen“ erstellt werden. Wir haben eine abstrakte Klasse Vehicle
, und verschiedene konkrete Klassen wie Car
und Bike
, die diese Klasse erweitern. Eine abstrakte Factory-Methode wird verwendet, um diese Fahrzeuge zu erstellen.
#include <iostream>
#include <string>
// Produktklasse (abstrakte Klasse)
class Vehicle {
public:
virtual void drive() = 0;
virtual ~Vehicle() = default;
};
// Konkretes Produkt: Auto
class Car : public Vehicle {
public:
void drive() override {
std::cout << "Fahrzeug: Auto fährt auf der Straße." << std::endl;
}
};
// Konkretes Produkt: Fahrrad
class Bike : public Vehicle {
public:
void drive() override {
std::cout << "Fahrzeug: Fahrrad fährt auf dem Radweg." << std::endl;
}
};
// Creator (abstrakte Factory)
class VehicleFactory {
public:
virtual Vehicle* createVehicle() = 0;
virtual ~VehicleFactory() = default;
};
// Konkrete Factory: Auto Factory
class CarFactory : public VehicleFactory {
public:
Vehicle* createVehicle() override {
return new Car();
}
};
// Konkrete Factory: Fahrrad Factory
class BikeFactory : public VehicleFactory {
public:
Vehicle* createVehicle() override {
return new Bike();
}
};
// Client-Code
int main() {
// Erstellen eines Fahrzeugs über die Factory
VehicleFactory* carFactory = new CarFactory();
Vehicle* car = carFactory->createVehicle();
car->drive();
VehicleFactory* bikeFactory = new BikeFactory();
Vehicle* bike = bikeFactory->createVehicle();
bike->drive();
// Aufräumen
delete car;
delete bike;
delete carFactory;
delete bikeFactory;
return 0;
}
Erklärung des C++-Beispiels
Im obigen Beispiel haben wir mehrere Klassen, die die Struktur des Factory Method Patterns implementieren:
- Produktklasse (
Vehicle
): Diese abstrakte Klasse stellt die grundlegende Schnittstelle für alle Fahrzeuge dar. Sie enthält eine reine virtuelle Methodedrive()
, die von den konkreten Fahrzeugtypen überschrieben wird. - Konkrete Produkte (
Car
undBike
): Die KlassenCar
undBike
sind die konkreten Implementierungen desVehicle
-Produkts. Jede dieser Klassen hat ihre eigene Implementierung derdrive()
-Methode, die das jeweilige Fahrzeugverhalten beschreibt. - Creator (
VehicleFactory
): Die abstrakte KlasseVehicleFactory
definiert die Factory-MethodecreateVehicle()
, die für die Erstellung einesVehicle
verantwortlich ist. Sie enthält auch einen virtuellen Destruktor, um eine korrekte Speicherfreigabe zu gewährleisten. - Konkrete Creator-Klassen (
CarFactory
undBikeFactory
): Diese Klassen implementieren diecreateVehicle()
-Methode, um konkrete Fahrzeugobjekte zu erstellen. DieCarFactory
erzeugt einCar
-Objekt, während dieBikeFactory
einBike
-Objekt erzeugt. - Client-Code: Im
main()
-Programm wird der Client-Code gezeigt, der verschiedene Factory-Objekte erstellt und derencreateVehicle()
-Methoden aufruft, um die gewünschten Fahrzeugobjekte zu erzeugen. Der Client-Code muss nicht wissen, welche konkreten Klassen instanziiert werden – dies übernimmt die Factory.
Vorteile des Factory Method Patterns
- Flexibilität: Das Factory Method Pattern ermöglicht es, neue Produkttypen hinzuzufügen, ohne dass der Client-Code geändert werden muss. Neue konkrete Factory-Klassen können erstellt werden, die neue Produkte erzeugen, ohne den Code, der diese Factory nutzt, anzupassen.
- Entkopplung: Der Client-Code ist vom konkreten Typ des zu erstellenden Objekts entkoppelt. Dies fördert die Wartbarkeit und Erweiterbarkeit des Codes.
- Erweiterbarkeit: Neue Produktarten und deren zugehörige Factory-Klassen können leicht hinzugefügt werden, ohne die bestehende Architektur zu stören.
- Zentralisierte Objektinstanziierung: Die Logik für die Objekterstellung wird in den Factory-Klassen zentralisiert, was den Code übersichtlicher und leichter zu verwalten macht.
Nachteile des Factory Method Patterns
- Komplexität: Durch das Hinzufügen von mehreren Factory-Klassen und abstrakten Basisklassen kann der Code komplexer und schwerer zu verstehen werden, besonders in einfachen Szenarien, in denen keine weitere Erweiterung erforderlich ist.
- Zusätzliche Klassen: Da für jedes Produkt eine eigene Factory-Klasse erstellt werden muss, kann dies zu einer größeren Anzahl von Klassen im Projekt führen, was die Übersichtlichkeit beeinträchtigen kann.
- Verborgene Abstraktionen: In einigen Fällen kann das Factory Method Pattern dazu führen, dass der Client-Code nicht direkt sieht, welches konkrete Produkt erstellt wird, was die Transparenz verringern kann.
Fazit
Das Factory Method Pattern ist ein mächtiges Entwurfsmuster, das die Flexibilität und Erweiterbarkeit von Softwareanwendungen fördert. Es ermöglicht eine saubere Trennung zwischen der Erstellung von Objekten und dem restlichen Code. Durch das Prinzip der „Factory“ können neue Produkttypen hinzugefügt werden, ohne dass der Client-Code geändert werden muss. Wie bei jedem Entwurfsmuster sollte auch das Factory Method Pattern jedoch mit Bedacht eingesetzt werden, da es zu einer erhöhten Komplexität führen kann, wenn es nicht richtig angewendet wird.
Zurück zur Liste: Liste der Design-Pattern