È così che puoi essere immutable AND simula i parametri denominati allo stesso tempo.
Person p = personBuilder
.name("Arthur Dent")
.age(42)
.build()
;
Ciò mantiene i tuoi mitts fuori dalla persona finché non viene impostato lo stato e, una volta impostato, non ti consente di cambiarlo, ma ogni campo è chiaramente etichettato. Non puoi farlo con una sola classe in Java.
Sembra che tu stia parlando di Josh Blochs Builder Pattern . Questo non deve essere confuso con il Gang di Four Builder Pattern . Queste sono bestie diverse. Entrambi risolvono i problemi di costruzione, ma in modi abbastanza diversi.
Ovviamente puoi costruire il tuo oggetto senza usare un'altra classe. Ma poi devi scegliere. Si perde la capacità di simulare i parametri con nome in lingue che non li hanno (come Java) o si perde la capacità di rimanere immutabili per tutta la durata degli oggetti.
Esempio immutabile, non ha nomi per i parametri
Person p = new Person("Arthur Dent", 42);
Qui stai costruendo tutto con un singolo semplice costruttore. Ciò ti consentirà di rimanere immutabile, ma perderai la simulazione dei parametri con nome. Questo diventa difficile da leggere con molti parametri. I computer non si preoccupano ma è difficile per gli umani.
Esempio di parametro con nome simulato con setter tradizionali. Non immutabile.
Person p = new Person();
p.name("Arthur Dent");
p.age(42);
Qui stai costruendo tutto con setter e simuli parametri con nome ma non sei più immutabile. Ogni utilizzo di un setter cambia stato dell'oggetto.
Quindi ciò che ottieni aggiungendo la classe è che puoi fare entrambe le cose.
Validazione può essere eseguita in build()
se un errore di runtime per un campo di età mancante è sufficiente per te. Puoi aggiornarlo e imporre che age()
venga chiamato con un errore del compilatore. Solo non con il modello del costruttore Josh Bloch.
Per questo è necessario un Lingua specifica di dominio interna (iDSL).
Ciò ti consente di chiedere che chiamino age()
e name()
prima di chiamare build()
. Ma non puoi farlo solo restituendo this
ogni volta. Ogni cosa che ritorna restituisce una cosa diversa che ti costringe a chiamare la prossima cosa.
L'uso potrebbe essere simile a questo:
Person p = personBuilder
.name("Arthur Dent")
.age(42)
.build()
;
Ma questo:
Person p = personBuilder
.age(42)
.build()
;
causa un errore del compilatore perché age()
è valido solo per chiamare il tipo restituito da name()
.
Questi iDSL sono estremamente potenti ( JOOQ o Java8 Stream per esempio) e sono molto utili da usare, specialmente se si utilizza un IDE con il completamento del codice, ma sono un bel po 'di lavoro da impostare. Consiglierei di salvarli per cose che avranno un bel po 'di codice sorgente scritto contro di loro.