Il articolo che hai linkato parla dell'utilizzo di Builder Pattern per creare un oggetto. Non c'è alcuna differenza concettuale tra farlo e usare un costruttore. Tratta semplicemente tutti i passaggi del Builder come una singola operazione.
Durante il processo di costruzione, non stai mutando un oggetto immutabile, perché l'oggetto non è considerato completamente costruito fino a quando non chiami Build()
sul builder, a quel punto avrai quindi un oggetto immutabile completamente costruito.
Questo vale anche per i costruttori. Molti costruttori hanno diversi passaggi all'interno del corpo del metodo costruttore. Tutti questi passaggi devono essere completati prima che l'oggetto sia considerato completamente costruito e ne consegua un oggetto immutabile utilizzabile.
Se vuoi rendere un nuovo oggetto immutabile da un oggetto immutabile esistente con alcuni dei valori modificati, ciò di cui ora hai bisogno è un nuovo costruttore o costruttore che prende un oggetto esistente come parametro e quindi imposta tutti gli attributi nel costruttore o nel costruttore che si desidera modificare.
Ad esempio:
public BookBuilder(Book book) {
this.isbn = book.getIsbn();
this.publicationYear = book.getPublicationYear();
this.reviews = book.getReviews();
}
E poi
Book originalBook = getRandomBook();
Book modifiedBook = new
BookBuilder(originalBook).isbn("123456").publicationYear(2011).build();
Il builder crea una copia del libro originale, chiama i metodi nelle tue interfacce fluenti per impostare i campi desiderati su nuovi valori, quindi il metodo build()
blocca il nuovo oggetto in qualche modo in modo che diventi immutabile.
Nota che l'autore fa due concessioni:
- Il builder è non thread safe, e
- Devi ancora fare copie di oggetti.
Quando usi i costruttori, puoi impostare e modificare final
o readonly
membri finché il costruttore termina l'esecuzione, a quel punto questi membri diventano non modificabili.