Design Patterns in Android – Builder

Builder

Il pattern Builder semplifica la creazione di oggetti in modo molto pulito e leggibile. È molto utile quando abbiamo alcune classi modello con molti parametri. Possiamo rendere alcuni di essi opzionali o richiesti, e non forziamo l’utente ad usare un ordine specifico (come nel costruttore). Usando il pattern Builder si ottiene l’elegante catena dei metodi. L’uso più comune è nella classe AlertDialog.Builder():

new AlertDialog.Builder(this)
.setTitle("Design Patterns")
.setMessage("Builder is awesome")
.create();

Come possiamo creare la classe Builder per il nostro uso?

Builder in pratica

Prevediamo di avere qualche classe modello per l’utente:

public class User {
private String firstName;
private String lastName;
private int age;
}

E invece di creare oggetti di questa classe usando i costruttori, vogliamo crearli usando il Builder pattern come questo:

new User.Builder()
.setFirstName("Leonardo")
.setLastName("da Vinci")
.setAge(67)
.create();

Come possiamo farlo? In primo luogo, abbiamo bisogno di creare la classe Builder dentro la classe User che avrà i metodi per costruire il nostro oggetto. La chiave per avere metodi concatenati è che i metodi costruttori restituiscono la classe Builder. Guardate l’esempio:

static class Builder {
private String firstName;
private String lastName;
private int age;
public Builder setFirstName(final String firstName) {
this.firstName = firstName;
return this;
}
public Builder setLastName(final String lastName) {
this.lastName = lastName;
return this;
}
public Builder setAge(final int age) {
this.age = age;
return this;
}
public User create() {
return new User(this);
}
}

Per ogni parametro abbiamo un setter – la differenza è che quei metodi restituiscono il tipo Builder. Alla fine abbiamo un metodo che usa il costruttore della classe User e restituisce l’oggetto User – qui è il posto dove il nostro casino è tenuto nascosto.

Allora, abbiamo bisogno di creare il costruttore con tutti i parametri nella classe modello User :

public class User {
private String firstName;
private String lastName;
private int age;
private User(final Builder builder) {
firstName = builder.firstName;
lastName = builder.lastName;
age = builder.age;
}
}

La cosa importante qui è che il costruttore User è privato, quindi non può essere accessibile dall’altra classe e dobbiamo usare Builder per creare un nuovo oggetto.

Ovviamente, possiamo rendere alcuni dei parametri richiesti (per ora sono tutti opzionali) modificando il nostro metodo create() e lanciando alcune eccezioni, per esempio:

public User create() {
User user = new User(firstName, lastName, age);
if (user.firstName.isEmpty()) {
throw new IllegalStateException(
"First name can not be empty!");
}
return user;
}

Ecco fatto. In questo modo abbiamo creato la nostra classe User.Builder()!

Builder – protip

Se sei stato abbastanza paziente da leggere tutto il post del blog, ho un consiglio per te riguardo al pattern Builder: puoi generare l’intera classe Builder usando IntelliJ!

Tutto quello che devi fare è mettere il cursore sul costruttore nella tua classe e scegliere Refactor -> Replace Constructor with Builder nel menu contestuale. La classe Builder con tutti i metodi sarà generata automaticamente, pronta per l’uso.

Puoi leggere di più qui: IntelliJ: Replace Constructor with Builder

Conclusione

Il pattern Builder è un ottimo approccio, non solo per le classi modello ma per ogni oggetto che ha più di tre o quattro parametri. Con un po’ di lavoro aggiuntivo, possiamo aumentare la leggibilità del nostro codice. I design pattern sono riconosciuti come le migliori pratiche, quindi è un grande vantaggio conoscerne alcuni e Builder è un buon esempio per iniziare.