제이온

[Effective Java] Item 2. Consider Builder if the Constructor Has Many Parameters

Creado: 2024-04-27

Creado: 2024-04-27 00:46

Patrón de constructor gradual

Tanto las fábricas estáticas como los constructores tienen dificultades para manejar adecuadamente una gran cantidad de parámetros. Por ejemplo, si una clase tiene 6 campos y queremos tener constructores para 2 parámetros, 3 parámetros, ..., podemos usar el patrón de constructor gradual, como se muestra a continuación.



Sin embargo, incluso esto puede resultar confuso al leer el código cuando hay muchos parámetros, y es posible confundir los parámetros del mismo tipo y ponerlos en el orden incorrecto.


Patrón JavaBeans

El patrón JavaBeans crea un objeto mediante un constructor sin parámetros y luego llama a los métodos setter para establecer los valores de los parámetros deseados.



El patrón JavaBeans permite crear instancias sin confundir los parámetros, incluso cuando hay muchos. Sin embargo, se deben llamar a varios métodos setter para crear una instancia, y la consistencia se pierde hasta que se completa el objeto. Por esta razón, la clase no puede ser inmutable.


Patrón Builder

El patrón Builder se usa con mayor frecuencia porque combina la estabilidad del patrón de constructor gradual con la legibilidad del patrón JavaBeans.

En lugar de crear el objeto directamente, el cliente obtiene un objeto Builder llamando al constructor con solo los parámetros obligatorios. Luego, usa una especie de métodos setter proporcionados por el objeto Builder para establecer los parámetros opcionales que desee. Finalmente, llama al método build() sin parámetros para obtener el objeto que necesita.



El constructor de la clase Builder recibe solo los parámetros obligatorios, y los parámetros opcionales se establecen mediante una especie de métodos setter. Finalmente, se crea el objeto NutritionFactsWithBuilderPattern completo mediante el método build(). La clase NutritionFactsWithBuilderPattern es inmutable y los métodos setter del Builder devuelven el propio Builder, por lo que se pueden encadenar. Este método se llama API fluida o encadenamiento de métodos.



Desde el punto de vista del cliente, el patrón Builder facilita la escritura y lectura del código.


El patrón Builder funciona bien con clases jerárquicas


La clase Pizza.Builder es un tipo genérico que utiliza una restricción de tipo recursivo, y agrega un método abstracto self() para admitir el encadenamiento de métodos sin conversión en subclases. En las subclases, solo necesita devolver esta instancia en este método abstracto.

Ahora, veamos la pizza de Nueva York y la pizza Calzone, que son subclases de Pizza, para experimentar la flexibilidad del patrón Builder.



El método build() definido por el Builder de cada subclase devuelve la subclase concreta. La capacidad de un método en una subclase para devolver un tipo que es un subtipo del tipo devuelto por el método en la superclase se denomina tipado de retorno covariante. Con esta función, el cliente no necesita realizar conversiones.



Desde el punto de vista del cliente, puede usar el enum de Pizza y el enum de cada subclase, y puede completar el objeto con los métodos apropiados para cada uno.


Desventajas del patrón Builder

  • Se debe crear un objeto Builder.
  • El código es prolijo.


Resumen

Si un constructor o un método de fábrica estático tiene muchos parámetros que manejar, considere usar el patrón Builder.


Fuentes

  • Effective Java

Comentarios0