Design Patterns - Eine Kurzanleitung für Abstract Factory.

Dies ist eine Kurzanleitung zur Beherrschung eines der am häufigsten verwendeten Entwurfsmuster, der Abstract Factory. Auch wenn die Codierungsbeispiele in C ++ vorliegen werden, können sie problemlos an alle Programmiersprachen wie Java, Python, C #, Javascript und andere angepasst werden.

Abstract Factory wird in die kreativen Entwurfsmuster eingeteilt, bei denen es ausschließlich um die Instanziierung von Klassen und Objekten geht. Genauer gesagt, wie Vererbung (Klassenerstellungsmuster) oder Delegierung (Objekterstellungsmuster) effektiv genutzt werden können. [von Design Patterns einfach erklärt]

Fabrikdefinition: "Es ist ein Gebäude oder eine Gruppe von Gebäuden, in denen Produkte hergestellt / hergestellt werden". Die Produkte werden dann auf eigene Verantwortung an die Kunden zur Verwendung gesendet. Gleichzeitig sind die Kunden in der Fabrik zahlreich, und es sollte für die Kunden ziemlich einfach sein, ihr Produkt zu bestellen. Ebenso einfach sollte es für die Fabrik sein, es an die Bedürfnisse des Kunden anzupassen.

Verbinden wir die Punkte, um dieses Entwurfsmuster zu verstehen. Wir verwenden es, wenn wir eine Schnittstelle für die Erstellung abhängiger Objekte benötigen, ohne deren konkrete Klassen angeben zu müssen. Gleichzeitig wollen wir die Konstruktion von „Produkten“ durch Vererbung einkapseln.

Schritt 1 - Schlüsselwörter

Die Definition von Schlüsselwörtern ist das Geheimrezept in dieser Reihe von Kurzanleitungen. Diese Methode hat mir geholfen, die Entwurfsmuster wirklich zu verstehen, sie in meinem Kopf fest zu codieren und die Unterschiede zwischen anderen Entwurfsmustern zu verstehen.

  1. Produkt: Es ist ein Objekt, das von einer Fabrik gebaut wurde und zu einer Objektfamilie gehört. Es ist sehr spezifisch, da es keine Abstraktion gibt. Beispiel: BMWdoorHandle, FordDoorHandle.
  2. Abstraktes Produkt: Dies ist eine übergeordnete Ansicht eines Produkts, die seine Familie definiert. Beispiel Türgriff, Türfenster
  3. Konkrete Fabrik: Es handelt sich um eine Fabrik, in der die Erstellung und Fertigstellung eines Produkts „physisch“ mikroverwaltet wird. Beispiel: BMWFactory, FordFactory.
  4. Abstract Factory: Ist eine Schnittstelle zum Erstellen von Familien verwandter oder abhängiger Objekte, ohne deren konkrete Klassen anzugeben. Beispiel: CarFactory

Schritt 2 - Diagramm

Bei der Diskussion über Abstract Factory sollte alles für die oben genannten Schlüsselwörter relevant sein. Wenn der Code von diesen Wörtern abweicht, stimmt wahrscheinlich etwas nicht. Machen wir es uns einfach: Concrete Factory erbt von Abstract Factory und Product von Abstract Product. Das Diagramm ist so einfach wie es aussieht; zwei Klassen, die von ihren abstrakten Klassen erben. Die Betonfabrik ist diejenige, die die Drecksarbeit erledigt, um bestimmte Produkte herzustellen (was durch die rote Linie gekennzeichnet ist). Mit diesem Diagramm ist es leicht zu verstehen, dass dieses Entwurfsmuster leicht aktualisiert werden kann, indem konkretere Fabriken und mehr Produkte hinzugefügt werden, d. H. ProductC, ProductD usw. Mit anderen Worten, dieses Bild kann nur breiter und definitiv nicht in der Höhe werden.

Schritt 3 - Code durch Beispiel

Ich würde vorschlagen, den Code Klasse für Klasse aus meinem Git-Repository „Andreas Poyias“ zu kopieren und in einen beliebigen Online-C ++ - Editor wie eine C ++ - Shell, ein JDoodle, eine Online-GDB oder einen anderen einzufügen und ihn auszuführen, um die Ausgabe zu beobachten. Dann lies die Kommentare oder die Beschreibung unten. Die Klassennamen sind so geschrieben, dass ich nach dem Unterstrich das dazugehörige Schlüsselwort gebe.

AbstractProduct
Das abstrakte Produkt ist eine abstrakte Klasse und definiert erwartungsgemäß eine Familie von Produkten, die von ihm erben. In diesem Beispiel ist das abstrakte Produkt aDoorHandle. Ich habe eine Funktion hinzugefügt, die etwas zum Präsentieren druckt.

#include 
Klasse DoorHandle_AbstractProduct
{
Öffentlichkeit:
 // Eine Dummy-Funktion, die etwas druckt
 virtuell void printSerialNumber () = 0;
};

Produkt
In diesem Beispiel sind die Produkte BMW oder Ford Türgriff. Sie haben unterschiedliche Seriennummern, daher kann jede Klasse ihre eigene produktspezifische Seriennummer drucken. Wir könnten auch DoorWindoworSteeringWheel haben. Die Türgriffklassen erben von der obigen abstrakten Klasse.

// BMW Türgriff [in der Familie der Türgriffe]
Klasse BMWDoorHandle_Product: public DoorHandle_AbstractProduct
{
Öffentlichkeit:
    // Gibt die produktspezifische Seriennummer aus
    void printSerialNumber () {
        std :: cout << "Türgriff_Produkt: BMW123 \ n";
    }
};
// Ford Türgriff [in der Familie der Türgriffe]
Klasse FordDoorHandle_Product: public DoorHandle_AbstractProduct
{
Öffentlichkeit:
    // Gibt die produktspezifische Seriennummer aus
    void printSerialNumber () {
        std :: cout << "Türgriff_Produkt: Ford123 \ n";
    }
};

AbstracFactory
 Dies ist eine sehr generische / abstrakte Klasse, die nicht viel mehr als die create-Funktionen haben sollte. Am Ende schafft eine Fabrik nur Produkte.

Klasse Car_AbstractFactory
{
Öffentlichkeit:
 virtual DoorHandle_AbstractProduct * createDoorHandle () = 0;
 // virtual DoorWindow_AbstractProduct * createDoorWindow () = 0;
};

ConcreteFactory
Diese Fabrikklasse ist sehr produktspezifisch. Es ist der harte Arbeiter, der das Puzzle zusammensetzt. In diesem Beispiel ist es spezifisch für eine Marke {BMW, Ford}. Ihre Aufgabe ist es, eine Instanz eines Produkts zurückzugeben, das für diese Marke spezifisch ist. Wenn wir BMWDoorWindow erstellen möchten, können wir tatsächlich eine neue Funktion erstellen, die eine Instanz der relevanten abstrakten Klasse zurückgibt. In meinem Git-Repository gibt es die vollständige Implementierung auch mit den DoorWindow-Teilen.

Klasse BMWCar_ConcreteFactory: public Car_AbstractFactory
{
Öffentlichkeit:
    DoorHandle_AbstractProduct * createDoorHandle () {
        neues BMWDoorHandle_Product zurückgeben;
    }
};
Klasse FordCar_ConcreteFactory: public Car_AbstractFactory
{
Öffentlichkeit:
    DoorHandle_AbstractProduct * createDoorHandle () {
        neues FordDoorHandle_Product zurückgeben;
    }
};

Hauptfunktion
Schließlich ist dies der letzte Code. Die Hauptfunktion, die als Client fungiert. Der Kunde kann problemlos Produkte ab Werk „bestellen“ und sie nach Belieben verwenden.

int main ()
{
    // Client benötigt ein doorHandle und ein doorWindow
    Car_AbstractFactory * abstractFactory;
    DoorHandle_AbstractProduct * dHandle_AbstractProduct;
 
    // Der Kunde benötigt Produkte der Marke Ford
    abstractFactory = new FordCar_ConcreteFactory;
    // Ford Betonfabrik schafft sie
    // und gibt sie an den Client zurück
    dHandle_AbstractProduct = abstractFactory-> createDoorHandle ();
    // Client verwendet die Produkte
    dHandle_AbstractProduct -> printSerialNumber ();
    // Jetzt will der Kunde doch Produkte von der Marke BMW
    abstractFactory = neue BMWCar_ConcreteFactory;
    // Also schafft die BMW Betonfabrik sie
    // und gibt sie an den Client zurück
    dHandle_AbstractProduct = abstractFactory-> createDoorHandle ();
    // Client verwendet die Produkte
    dHandle_AbstractProduct -> printSerialNumber ();
return 0;
}
// Ausgabe
// Türgriff_Produkt: Ford123
// Türgriff_Produkt: BMW123

Die Vorteile sind möglicherweise nicht sofort ersichtlich. Stellen Sie sich für eine Sekunde vor, wie viele Produkte ein Auto hat und wie viele Dinge eine Autofabrik tun kann. Stellen Sie sich nun das Chaos vor, bei jeder Entscheidung von BMW, einen Türgriff zu ändern, einen schlecht gestalteten Code beizubehalten. Fügen Sie eine neue Art von Fahrersitz hinzu oder ändern Sie sogar etwas am Motor. Stellen Sie sich vor, Sie könnten diese Probleme nun noch komplexer machen, aber für mehrere Marken. Abstract Factory bietet einen wartungsfreundlichen und sauberen Ansatz, der über Jahre hinweg genutzt werden kann. Es wäre schwierig für einen neuen Entwickler, Fehler zu machen und ein neues Produkt so einfach hinzuzufügen / zu entfernen.

Abstrakte Fabrik ist erst der Anfang dieser Reise. Dies ist eines der am häufigsten verwendeten Entwurfsmuster und wird häufig in Kombination mit anderen Entwurfsmustern verwendet. Der nächste Blog wird eine Kurzanleitung für das Singleton-Designmuster sein. Vergessen Sie nicht, meinen Blog zu mögen und meinem Konto zu folgen. Dies soll mir die Befriedigung geben, dass ich einigen Mitentwicklern geholfen habe und mich dazu drängen, weiter zu schreiben.

Weitere Kurzanleitungen zu Entwurfsmustern:

  1. Design Patterns - Eine Kurzanleitung für Abstract Factory.
  2. Design Patterns - Eine Kurzanleitung für Bridge Pattern.
  3. Entwurfsmuster - Eine Kurzanleitung zum Builder-Muster.
  4. Design Patterns - Eine Kurzanleitung für Decorator Patterns.
  5. Entwurfsmuster - Eine Kurzanleitung für Fassadenmuster.
  6. Design Patterns - Eine Kurzanleitung für Observer Patterns.
  7. Entwurfsmuster - Eine Kurzanleitung für Singleton-Muster.