Einführung
In der Softwareentwicklung beschreibt ein Entwurfsmuster eine etablierte Lösung für die am häufigsten auftretenden Probleme in Software Design. Es stellt die Best Practices dar, die über einen langen Zeitraum durch Versuch und Irrtum erfahrener Softwareentwickler entwickelt wurden.
Design Patterns wurden immer beliebter, nachdem das Buch Design Patterns: Elemente wiederverwendbarer objektorientierter Software 1994 von Erich Gamma veröffentlicht wurde , John Vlissides, Ralph Johnson und Richard Helm (auch bekannt als Gang of Four oder GoF).
In diesem Artikel werden wir uns mit kreativen Designmustern und ihren Typen befassen. Wir werden uns auch einige ansehen Codebeispiele und diskutieren die Situationen, in denen diese Muster zu unserem Design passen.
Kreative Designmuster
Kreative Designmuster befassen sich mit der Art und Weise, wie Objekte erstellt werden . Sie reduzieren Komplexität und Instabilität, indem sie Objekte auf kontrollierte Weise erstellen.
Der neue Operator wird häufig als schädlich angesehen, da er Objekte in der gesamten Anwendung streut. Im Laufe der Zeit kann es schwierig werden, eine Implementierung zu ändern, da Klassen eng miteinander verbunden sind.
Mit Entwurfsmustern wird dieses Problem behoben, indem der Client vollständig vom eigentlichen Initialisierungsprozess entkoppelt wird.
In diesem Artikel Wir werden vier Arten von Erstellungsentwurfsmustern diskutieren:
- Singleton – Stellt sicher, dass höchstens eine Instanz eines Objekts in der gesamten Anwendung vorhanden ist.
- Factory-Methode – Erstellt Objekte von mehrere verwandte Klassen ohne Angabe des genauen zu erstellenden Objekts
- Abstract Factory – Erstellt Familien verwandter abhängiger Objekte
- Builder – Konstruiert komplexe Objekte mithilfe eines schrittweisen Ansatzes
Lassen Sie uns nun jedes dieser Muster im Detail diskutieren.
Singleton-Entwurfsmuster
Das Singleton-Entwurfsmuster soll beibehalten werden Eine Überprüfung der Initialisierung von Objekten einer bestimmten Klasse, indem sichergestellt wird, dass nur eine Instanz des Objekts in der gesamten Java Virtual Machine vorhanden ist.
Eine Singleton-Klasse stellt außerdem einen eindeutigen globalen Zugriffspunkt für das Objekt bereit, sodass bei jedem nachfolgenden Aufruf des Zugriffspunkts nur dieses bestimmte Objekt zurückgegeben wird.
3.1. Beispiel für ein Singleton-Muster
Obwohl das Singleton-Muster von GoF eingeführt wurde, ist bekannt, dass die ursprüngliche Implementierung in Multithread-Szenarien problematisch ist.
Also hier “ Wir werden einen optimaleren Ansatz verfolgen, der eine statische innere Klasse verwendet:
Hier haben wir eine statische innere Klasse erstellt, die die Instanz der Singleton-Klasse enthält. Die Instanz wird nur erstellt, wenn jemand die Methode getInstance () aufruft und nicht, wenn die äußere Klasse geladen ist.
Dies ist ein weit verbreiteter Ansatz für eine Singleton-Klasse, da keine Synchronisierung erforderlich ist und threadsicher ist , erzwingt eine verzögerte Initialisierung und hat vergleichsweise weniger Boilerplate.
Beachten Sie außerdem, dass der Konstruktor über den Modifikator für den privaten Zugriff verfügt. Dies ist eine Voraussetzung für die Erstellung eines Singleton, da ein öffentlicher Konstruktor bedeuten würde, dass jeder darauf zugreifen und neue Instanzen erstellen kann.
Denken Sie daran, dass dies nicht die ursprüngliche GoF-Implementierung ist. Die Originalversion finden Sie hier verknüpfter Baeldung-Artikel zu Singletons in Java.
3.2. Wann wird das Singleton-Entwurfsmuster verwendet?
- Für Ressourcen, deren Erstellung teuer ist (z. B. Datenbank) Verbindungsobjekte)
- Es wird empfohlen, alle Logger als Singletons beizubehalten, um die Leistung zu steigern.
- Klassen, die Zugriff auf Konfigurationseinstellungen für die Anwendung bieten
- Klassen, die Ressourcen enthalten, auf die im freigegebenen Modus zugegriffen wird
Entwurfsmuster für Factory-Methoden
Das Factory-Entwurfsmuster oder das Entwurfsmuster für Factory-Methoden ist eines der folgenden am häufigsten verwendete Entwurfsmuster in Java.
Laut GoF definiert dieses Muster „eine Schnittstelle zum Erstellen eines Objekts, lässt jedoch Unterklassen entscheiden, welche Klasse installiert werden soll tiate. Mit der Factory-Methode kann eine Klasse die Instanziierung auf Unterklassen verschieben. “
Dieses Muster delegiert die Verantwortung für die Initialisierung einer Klasse vom Client an eine bestimmte Factory-Klasse, indem ein Typ eines virtuellen Konstruktors erstellt wird.
Um dies zu erreichen, verlassen wir uns auf eine Factory, die uns die Objekte zur Verfügung stellt und die tatsächlichen Implementierungsdetails verbirgt. Auf die erstellten Objekte wird über eine gemeinsame Schnittstelle zugegriffen.
4.1. Beispiel für ein Entwurfsmuster für Factory-Methoden
In diesem Beispiel erstellen wir eine Polygon-Schnittstelle, die von mehreren konkreten Klassen implementiert wird. Eine PolygonFactory wird zum Abrufen von Objekten aus dieser Familie verwendet :
Lassen Sie uns zuerst die Polygon-Schnittstelle erstellen:
Weiter, Wir werden einige Implementierungen wie Quadrat, Dreieck usw. erstellen, die diese Schnittstelle implementieren und ein Objekt vom Typ Polygon zurückgeben.
Jetzt können wir eine Factory erstellen, die die Anzahl der Seiten als Argument verwendet und die entsprechende Implementierung dieser Schnittstelle zurückgibt:
Beachten Sie, wie sich der Client auf diese Factory verlassen kann, um uns zu geben ein geeignetes Polygon, ohne das Objekt direkt initialisieren zu müssen.
4.2. Wann wird das Entwurfsmuster für Factory-Methoden verwendet?
- Wenn sich die Implementierung einer Schnittstelle oder einer abstrakten Klasse voraussichtlich häufig ändert
- Wenn die aktuelle Implementierung kann neue Änderungen nicht bequem aufnehmen
- Wenn der Initialisierungsprozess relativ einfach ist und der Konstruktor nur eine Handvoll Parameter benötigt
Abstraktes Factory-Entwurfsmuster
Im vorherigen Abschnitt haben wir gesehen, wie das Entwurfsmuster der Factory-Methode verwendet werden kann, um Objekte zu erstellen, die sich auf eine einzelne Familie beziehen.
Im Gegensatz dazu wird das abstrakte Factory-Entwurfsmuster verwendet um Familien verwandter oder abhängiger Objekte zu erstellen. Es wird manchmal auch als Fabrik von Fabriken bezeichnet.
Eine ausführliche Erklärung finden Sie in unserem Tutorial zu Abstract Factory.
Builder-Entwurfsmuster
Das Builder-Entwurfsmuster ist ein weiteres Erstellungsmuster, das für die Konstruktion vergleichsweise komplexer Objekte entwickelt wurde.
Wenn die Komplexität beim Erstellen von Objekten zunimmt, kann das Builder-Muster den Instanziierungsprozess mithilfe eines anderen trennen Objekt (ein Builder) zum Erstellen des Objekts.
Dieser Builder kann dann verwendet werden, um viele andere ähnliche Darstellungen mithilfe eines einfachen schrittweisen Ansatzes zu erstellen.
6.1. Builder-Muster Beispiel
Das von GoF eingeführte ursprüngliche Builder-Entwurfsmuster konzentriert sich auf die Abstraktion und ist sehr gut im Umgang mit komplexen Objekten, der Entwurf ist jedoch etwas kompliziert.
oshua Bloch hat in seinem Buch Effective Java eine verbesserte Version des Builder-Musters vorgestellt, die sauber und gut lesbar ist (weil sie verwendet wird) fließendes Design) und aus Kundensicht einfach zu bedienen. In diesem Beispiel wird diese Version erläutert.
In diesem Beispiel gibt es nur eine Klasse, BankAccount, die einen Builder als statische innere Klasse enthält:
Beachten Sie, dass alle Zugriffsmodifikatoren in den Feldern als privat deklariert sind, da äußere Objekte nicht direkt auf sie zugreifen sollen.
Der Konstruktor ist auch privat, sodass nur der Builder diesem zugewiesen ist Klasse kann darauf zugreifen. Alle im Konstruktor festgelegten Eigenschaften werden aus dem Builder-Objekt extrahiert, das wir als Argument angeben.
Wir haben BankAccountBuilder in einer statischen inneren Klasse definiert:
Beachten Sie, dass wir denselben Satz von Feldern deklariert haben, den die äußere Klasse enthält. Alle Pflichtfelder sind als Argumente für den Konstruktor der inneren Klasse erforderlich, während die verbleibenden optionalen Felder mithilfe der Setter-Methoden angegeben werden können.
Diese Implementierung unterstützt auch den fließenden Entwurfsansatz, indem die Setter-Methoden den Builder zurückgeben Objekt.
Schließlich ruft die Erstellungsmethode den privaten Konstruktor der äußeren Klasse auf und übergibt sich selbst als Argument. Das zurückgegebene BankAccount wird mit den vom BankAccountBuilder festgelegten Parametern instanziiert.
Sehen wir uns ein kurzes Beispiel für das Builder-Muster in Aktion an:
6.2. Verwendung des Builder-Musters
- Wenn der Prozess zum Erstellen eines Objekts äußerst komplex ist und viele obligatorische und optionale Parameter enthält
- Wenn ein Eine Erhöhung der Anzahl der Konstruktorparameter führt zu einer großen Liste von Konstruktoren.
- Wenn der Client unterschiedliche Darstellungen für das Objekt erwartet, das erstellt wurde
Schlussfolgerung
In diesem Artikel haben wir uns mit kreativen Entwurfsmustern in Java vertraut gemacht. Außerdem haben wir ihre vier verschiedenen Typen besprochen, dh Singleton, Factory-Methode, Abstract Factory- und Builder-Muster, ihre Vorteile, Beispiele und wann sollte Wir verwenden sie.
Wie immer sind die vollständigen Codefragmente auf GitHub verfügbar.
Beginnen Sie mit Spring 5 und Spring Boot 2 über den Learn Spring-Kurs:
> > PRÜFEN SIE DEN KURS