제이온

[Effective Java] Item 2: Erwäge einen Builder, wenn der Konstruktor viele Parameter hat

  • Verfasst in: Koreanisch
  • Land: Alle Ländercountry-flag
  • IT

Erstellt: 2024-04-27

Erstellt: 2024-04-27 00:46

Graduelles Builder-Pattern

Sowohl statische Fabriken als auch Konstruktoren sind bei einer großen Anzahl von Parametern schwer zu handhaben. Wenn beispielsweise eine Klasse 6 Felder hat und man Konstruktoren für 2, 3 usw. Parameter erstellen möchte, kann man das Graduelle Builder-Pattern verwenden, wie unten gezeigt.



Aber selbst das kann bei einer größeren Anzahl von Parametern zu Problemen führen. Es wird schwer, beim Lesen des Codes die Bedeutung der einzelnen Werte zu verstehen, und man kann Parameter gleichen Typs verwechseln und falsche Werte zuweisen.


JavaBeans-Pattern

Das JavaBeans-Pattern erstellt ein Objekt mit einem parameterlosen Konstruktor und setzt die gewünschten Parameterwerte anschließend über Setter-Methoden.



Das JavaBeans-Pattern ermöglicht es, auch bei einer großen Anzahl von Parametern Objekte ohne Verwechslungsgefahr zu erstellen. Allerdings muss man für die Erstellung eines Objekts mehrere Setter-Methoden aufrufen, und bis das Objekt vollständig erstellt ist, ist die Konsistenz nicht gewährleistet. Daher kann die Klasse nicht unveränderlich sein.


Builder-Pattern

Das Builder-Pattern kombiniert die Zuverlässigkeit des Graduellen Builder-Patterns mit der Lesbarkeit des JavaBeans-Patterns und wird daher am häufigsten verwendet.

Anstatt das gewünschte Objekt direkt zu erstellen, ruft der Client einen Konstruktor mit den erforderlichen Parametern auf, um ein Builder-Objekt zu erhalten. Anschließend setzt er die gewünschten optionalen Parameter über die Setter-Methoden des Builder-Objekts. Schließlich ruft er die parameterlose Methode build() auf, um das gewünschte Objekt zu erhalten.



Der Konstruktor der Builder-Klasse akzeptiert nur die erforderlichen Parameter, und die restlichen optionalen Parameter werden über eine Art Setter-Methode hinzugefügt. Schließlich wird über die Methode build() ein vollständiges NutritionFactsWithBuilderPattern-Objekt erstellt. Die Klasse NutritionFactsWithBuilderPattern ist unveränderlich, und die Setter-Methoden des Builders geben den Builder selbst zurück, sodass sie ineinander verschachtelt aufgerufen werden können. Diese Vorgehensweise wird als Fluent API oder Methodenverkettung bezeichnet.



Aus Sicht des Clients ist das Builder-Pattern einfach zu schreiben und zu lesen.


Das Builder-Pattern passt gut zu hierarchisch strukturierten Klassen


Die Klasse Pizza.Builder ist ein generischer Typ, der rekursive Typparameter verwendet, und sie enthält die abstrakte Methode self(), die es Unterklassen ermöglicht, die Methodenverkettung zu unterstützen, ohne Typumwandlungen durchführen zu müssen. Die Unterklassen geben einfach sich selbst als Rückgabewert dieser abstrakten Methode zurück.

Schauen wir uns nun die Unterklassen New York Pizza und Calzone Pizza an, um die Flexibilität des Builder-Patterns zu demonstrieren.



Die build()-Methode jeder Unterklassen-Builder-Klasse gibt die konkrete Unterklasse zurück. Die Fähigkeit einer Methode einer Unterklasse, einen Typ zurückzugeben, der ein Untertyp des Typs ist, der von der entsprechenden Methode der Oberklasse zurückgegeben wird, wird als kovariante Rückgabetypisierung bezeichnet. Dank dieser Funktion müssen Clients keine Typumwandlungen durchführen.



Der Client kann das Pizza-Enum und die Enums der jeweiligen Unterklassen mischen und das Objekt mit den entsprechenden Methoden vervollständigen.


Nachteile des Builder-Patterns

  • Ein Builder-Objekt muss erstellt werden.
  • Der Code kann umfangreich sein.


Zusammenfassung

Wenn Konstruktoren oder statische Fabrikmethoden eine große Anzahl von Parametern verarbeiten müssen, sollten Sie das Builder-Pattern in Betracht ziehen.


Quellen

  • Effective Java

Kommentare0