Ejemplo del patrón de diseño Builder

Publicado por pico.dev el , actualizado el .
blog-stack java planeta-codigo programacion
Comentarios

Construir objetos es una tarea básica en los lenguajes orientados a objetos. En Java, las instancias de una clase se crean con la palabra clave reservada new y un método especial llamado constructor. Al diseñar una clase debemos tener algunas cuestiones para evitar varios constructores telescópicos, evitar constructores que son combinación de varios argumentos opcionales y permitir obtener instancias de objetos con estado válido. Si se nos presentan estas situaciones podemos usar el patrón de diseño Builder que consiste en básicamente en una clase especializada en construir instancias de otra clase que podemos hacer usable con una API fluida y alguna cosa más deseable que explico en el artículo.

Java

Al escribir los métodos constructores de instancias de una clase puede ocurrirnos que algunos de ellos tienen una lista larga de argumentos (cuatro o más parámetros puede considerarse larga) o el caso de que otros algunos argumentos son opcionales. En el caso de una lista larga de argumentos algunos puedan tomar valores por defecto creando métodos telescópicos (donde hay varios constructores y cada uno solo añade un nuevo argumento al anterior), en el caso de argumentos opcionales nos obliga a crear un constructor por cada combinación de argumentos, peor aún, ambas cosas se pueden producir a la vez.

Por ejemplo, supongamos que tenemos una entidad de dominio Usuario en la que el correo electrónico es requerido siendo opcionales su nombre, apellidos teléfono o dirección. Sin usar el patrón de diseño Builder probablemente tendríamos los siguientes constructores o tener solo el último de ellos y en los no necesarios usar como valor del argumento null.

Como vemos no son pocos constructores debido a las combinaciones de los parámetros opcionales, esta forma requiere una buena cantidad de líneas de código y si decidiesemos escribir solo el constructor con todos los parámetros al usarlo tendremos dificultades para saber a que argumento responde cada variable y probablemente deberemos consultar la firma del constructor para saber que lugar ocupa cada argumento, esto dificulta la legibilidad.

En este caso solo hay tres argumentos opcionales si hubiera más el número de combinaciones y por tanto de constructores aumentaría considerablemente. Puede que en vez de usar constructores usemos un método set de JavaBean de forma que tengamos un solo constructor y múltiples métodos set o un constructor con los argumentos requeridos y un set por cada argumento opcional.

Sin embargo, esta solución aunque permite reducir el número de constructores también tiene problemas, uno de ellos es que el constructor y los set no obligan a crear un objeto con estado consistente o válido, otro es que usando los set de los JavaBean nos impide hacer el objeto inmutable, si no es devolviendo una nueva instancia, que con las nuevas características funcionales añadidas en Java 8 y en la programación cocurrente es deseable.

La solución a los constructores telescópicos y combinación de argumentos es usar el patrón de diseño Builder. Por ejemplo, empleando el mismo caso que los anteriores de la siguiente forma.

Su uso sería de la siguiente manera algo más autoexplicativa y legible que la opción de usar constructores.

La instancia de la clase UsuarioBuilder en su uso recoge los datos usando una API fluida, el método build es el que construye la instancia del usuario mediante el constructor con visibilidad de paquete en el que se valida que los datos al construir el objeto Usuario sean válidos, en este caso que el email es requerido.

En el libro Effective Java en el Item #2 se comenta más detalladamente este patrón junto a otra buena colección de cosas sobre los constructores y más cosas sobre Java, es uno en mi lista de 8+ libros recomendables para mejorar como programadores.

En el apartado de referencia puedes encontrar más artículos que he escrito sobre otros patrones de diseño.

Yo apoyo al software libre