Patrones de diseño en Android – Builder

Builder

El patrón Builder simplifica la creación de objetos de forma muy limpia y legible. Es muy útil cuando tenemos algunas clases modelo con muchos parámetros. Podemos hacer que algunos de ellos sean opcionales o requeridos, y no obligamos al usuario a utilizar un orden específico (como en el constructor). Usando el patrón Builder resultamos con la elegante cadena de los métodos. El uso más común es en la clase AlertDialog.Builder():

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

¿Cómo podemos crear la clase Builder para nuestro propio uso?

Builder en la práctica

Supongamos que tenemos alguna clase modelo para el usuario:

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

Y en lugar de crear objetos de esta clase usando constructores, queremos crearlos usando el patrón Builder así:

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

¿Cómo podemos hacerlo? En primer lugar, tenemos que crear la clase Builder dentro de la clase User que tendrá los métodos para construir nuestro objeto. La clave para tener métodos de encadenamiento es que los métodos del constructor devuelven la clase Builder. Mira el ejemplo:

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);
}
}

Para cada parámetro tenemos un setter – la diferencia es que esos métodos devuelven la clase Builder. Al final tenemos un método que utiliza el constructor de la clase User y devuelve el objeto User – aquí es el lugar donde nuestro lío se mantiene oculto.

Entonces, tenemos que crear el constructor con todos los parámetros en la clase modelo 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;
}
}

Lo importante aquí es que el constructor User es privado, por lo que no se puede acceder desde la otra clase y debemos utilizar Builder para crear un nuevo objeto.

Por supuesto, podemos hacer que alguno de los parámetros sea obligatorio (ya que por ahora todos son opcionales) modificando nuestro método create() y lanzando algunas excepciones, por ejemplo:

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;
}

Eso es todo. De esta manera creamos nuestra clase User.Builder()

Builder – protip

Si has sido lo suficientemente paciente como para llegar a través de toda la entrada del blog, tengo un consejo para ti en relación con el patrón Builder: puedes generar toda la clase Builder usando IntelliJ!

Todo lo que necesitas hacer es colocar el caret en el constructor de tu clase y elegir Refactor -> Replace Constructor with Builder en el menú contextual. La clase constructora con todos los métodos se autogenerará, lista para su uso.

Puedes leer más aquí: IntelliJ: Replace Constructor with Builder

Conclusión

El patrón Builder es un gran enfoque, no sólo para las clases modelo sino para todo objeto que tenga más de tres o cuatro parámetros. Con un poco de trabajo adicional, podemos aumentar la legibilidad de nuestro código. Los patrones de diseño son reconocidos como la mejor práctica, por lo que es una gran ventaja si usted sabe algunos de ellos y Builder es uno bueno para empezar.