Ich habe kürzlich eine Java- Antwort von mir auf Code Review gelöscht , die so begann:
private Person(PersonBuilder builder) {
Halt. Rote Flagge. Ein PersonBuilder würde eine Person erstellen. es kennt eine Person. Die Person-Klasse sollte nichts über einen PersonBuilder wissen - es ist nur ein unveränderlicher Typ. Sie haben hier eine kreisförmige Kopplung erstellt, wobei A von B abhängt, was von A abhängt.
Die Person sollte nur ihre Parameter aufnehmen; Ein Kunde, der bereit ist, eine Person zu erstellen, ohne sie zu erstellen, sollte dazu in der Lage sein.
Ich wurde mit einer Gegenstimme geschlagen und sagte, dass (unter Berufung auf) Red Flag, warum? Die Implementierung hier hat dieselbe Form, die Joshua Bloch in seinem Buch "Effective Java" (Punkt 2) demonstriert hat.
Es sieht also so aus, als ob die einzig richtige Methode zum Implementieren eines Builder-Musters in Java darin besteht , den Builder in einen verschachtelten Typ zu verwandeln (es handelt sich jedoch nicht um diese Frage) und dann das Produkt (die Klasse des zu erstellenden Objekts) zu erstellen ) nimm eine Abhängigkeit vom Builder , wie folgt:
private StreetMap(Builder builder) { // Required parameters origin = builder.origin; destination = builder.destination; // Optional parameters waterColor = builder.waterColor; landColor = builder.landColor; highTrafficColor = builder.highTrafficColor; mediumTrafficColor = builder.mediumTrafficColor; lowTrafficColor = builder.lowTrafficColor; }
Dieselbe Wikipedia-Seite für dasselbe Builder-Muster hat eine völlig andere (und viel flexiblere) Implementierung für C #:
//Represents a product created by the builder public class Car { public Car() { } public int Wheels { get; set; } public string Colour { get; set; } }
Wie Sie sehen, weiß das Produkt hier nichts über eine Builder
Klasse, und wenn es auch wichtig ist, könnte es durch einen direkten Konstruktoraufruf, eine abstrakte Factory, ... oder einen Builder instanziiert werden - soweit ich das verstehe Produkt eines Schöpfungsmusters muss nie etwas darüber wissen, was es schafft.
Mir wurde das Gegenargument zugestellt (das anscheinend ausdrücklich in Blochs Buch verteidigt wird), dass ein Builder-Muster verwendet werden könnte, um einen Typ zu überarbeiten, bei dem ein Konstruktor mit Dutzenden optionaler Argumente aufgebläht wäre. Anstatt mich an das zu halten, von dem ich dachte, dass ich es wüsste, habe ich ein bisschen auf dieser Seite recherchiert und festgestellt, dass dieses Argument , wie ich vermutete, kein Wasser hält .
Also, was ist der Deal? Warum überarbeitete Lösungen für ein Problem finden, das es eigentlich gar nicht geben sollte? Wenn wir Joshua Bloch für eine Minute von seinem Podest nehmen, können wir einen einzigen guten, gültigen Grund finden, zwei konkrete Typen zu koppeln und es als Best Practice zu bezeichnen?
Das alles riecht für mich nach Frachtkult-Programmierung .