Recentemente ho eliminato una java risposta mia su Analisi del codice , che è iniziata così:
private Person(PersonBuilder builder) {
Stop. Red flag. A PersonBuilder would build a Person; it knows about a Person. The Person class shouldn't know anything about a PersonBuilder - it's just an immutable type. You've created a circular coupling here, where A depends on B which depends on A.
The Person should just intake its parameters; a client that's willing to create a Person without building it should be able to do that.
Sono stato schiaffeggiato con un downvote, e ho detto che (citando) Bandiera rossa, perché? L'implementazione qui ha la stessa forma mostrata da Joshua Bloch nel suo libro "Effective Java" (articolo # 2).
Quindi, sembra che il modo One Right di implementare un Pattern Builder in Java sia rendi il builder un tipo annidato (non è questa la domanda però) e poi fai product (la classe dell'oggetto che viene creato) prendi una dipendenza sul builder , come questo:
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 di 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 classe Builder
, e per quanto ne pensi potrebbe essere istanziata da una chiamata diretta al costruttore, una fabbrica astratta, .. .o un costruttore: per quanto ho capito, il prodotto di un modello creativo mai deve sapere qualcosa su cosa lo sta creando.
Mi è stato servito il contro-argomento (che apparentemente è esplicitamente difeso nel libro di Bloch) che un modello di builder potrebbe essere usato per rielaborare un tipo che avrebbe un generatore gonfiato con dozzine di argomenti opzionali. Quindi, invece di attenermi a ciò che pensavo , sapevo di aver fatto ricerche un po 'su questo sito e ho scoperto che, come sospettavo, questo argomento non contiene acqua .
Quindi qual è il problema? Perché proporre soluzioni troppo ingegnerizzate a un problema che non dovrebbe nemmeno esistere in primo luogo? Se prendiamo Joshua Bloch dal suo piedistallo per un minuto, possiamo trovare una sola buona, valida ragione per accoppiare due tipi concreti e definirla una best practice?
Questo mi fa impazzire programmazione settoriale cargo .