Di recente ho eliminato una mia risposta Java su Code Review , che è iniziata in questo modo:
private Person(PersonBuilder builder) {
Fermare. Bandiera rossa. Un PersonBuilder costruirà una persona; sa di una persona. La classe Person non dovrebbe sapere nulla di PersonBuilder: è solo un tipo immutabile. Hai creato un accoppiamento circolare qui, dove A dipende da B che dipende da A.
La persona dovrebbe semplicemente assumere i suoi parametri; un cliente disposto a creare una Persona senza costruirla dovrebbe essere in grado di farlo.
Sono stato schiaffeggiato con un voto negativo e mi è stato detto che (citando) la bandiera rossa, perché? L'implementazione qui ha la stessa forma di quella dimostrata da Joshua Bloch nel suo libro "Effective Java" (oggetto n. 2).
Quindi, sembra che il modo giusto di implementare un Builder Pattern in Java sia di rendere il builder un tipo nidificato (non è di questo che si tratta questa domanda), e quindi rendere il prodotto (la classe dell'oggetto che si sta costruendo ) prendere una dipendenza dal costruttore , in questo modo:
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; }
La stessa pagina di Wikipedia per lo stesso modello Builder ha un'implementazione molto diversa (e molto più flessibile) per C #:
//Represents a product created by the builder public class Car { public Car() { } public int Wheels { get; set; } public string Colour { get; set; } }
Come puoi vedere, il prodotto qui non sa nulla di una Builder
classe, e per quanto gli interessi potrebbe essere istanziato da una chiamata diretta del costruttore, una fabbrica astratta, ... o un costruttore - per quanto ne capisco, il il prodotto di un modello creazionale non ha mai bisogno di sapere nulla di ciò che lo crea.
Mi è stato offerto il controargomentazione (che apparentemente è esplicitamente difeso nel libro di Bloch) secondo cui un modello di costruttore potrebbe essere usato per rielaborare un tipo che avrebbe un costruttore gonfio con dozzine di argomenti opzionali. Quindi, invece di attenermi a ciò che pensavo di sapere, ho studiato un po 'su questo sito e ho scoperto che, come sospettavo, questo argomento non regge .
Quindi qual è il problema? Perché trovare soluzioni troppo ingegnerizzate a un problema che non dovrebbe nemmeno esistere in primo luogo? Se togliiamo Joshua Bloch dal suo piedistallo per un minuto, possiamo trovare un unico buon motivo valido per accoppiare due tipi concreti e definirlo una buona pratica?
Tutto questo per me puzza di programmazione di culto delle merci .