Ecco una variante della risposta di Matt , utilizzando il modello di builder combinato con le nuove funzionalità funzionali di Java 8:
Book.java
import java.util.*;
import java.util.function.Consumer;
public class Book
{
private String title;
private List<String> authors;
private int year;
public Book(String title, List<String> authors, int year) {
this.title = title;
this.authors = new ArrayList<>(authors);
this.year = year;
}
/*
* Start with the current Book, create a BookBuilder with all the same properties, then send that through a functional lambda for changing what needs changed.
*/
public Book cloneWith(Consumer<BookBuilder> bookRebuilder) {
BookBuilder bookBuilder = new BookBuilder(getTitle(), getAuthors(), getYear());
bookRebuilder.accept(bookBuilder);
return new Book(bookBuilder.getTitle(), bookBuilder.getAuthors(), bookBuilder.getYear());
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
public List<String> getAuthors() {
return new ArrayList<String>(authors);
}
public String toString() {
StringBuilder str = new StringBuilder();
str.append(title);
str.append(", by ");
for(String author : authors) {
str.append(author);
str.append(", ");
}
str.append("published ");
str.append(year);
return str.toString();
}
}
BookBuilder.java (potrebbe essere altrettanto facilmente una classe interna statica)
import java.util.*;
public class BookBuilder
{
private String title;
private List<String> authors;
private int year;
public BookBuilder(String title, List<String> authors, int year) {
this.title = title;
this.authors = authors;
this.year = year;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getAuthors() {
return authors;
}
public void setAuthors(List<String> authors) {
this.authors = authors;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
Main.java
import java.util.*;
public class Main
{
public static void main(String[] args) {
Book book1 = new Book("Pride and Prejudice", Arrays.asList("Jane Austen"), 1813);
Book book2 = book1.cloneWith((baseBook)-> {
baseBook.setTitle("Pride and Prejudice and Zombies");
baseBook.setYear(2009);
List<String> authors = baseBook.getAuthors();
authors.add("Seth Grahame-Smith");
baseBook.setAuthors(authors);
});
System.out.println(book1.toString());
System.out.println(book2.toString());
}
}
Una grande differenza è che, invece di dover utilizzare una catena di chiamate fluide che potrebbero essere difficili da violare, possiamo intervenire con altre logiche all'interno della chiusura lambda. Qui BookBuilder
potrebbe anche essere reso fluido in modo che possa essere altrettanto preciso.