A menudo veo que la implementación del patrón de construcción (en Java) es así:
public class Foo {
private Foo(FooBuilder builder) {
// get alle the parameters from the builder and apply them to this instance
}
public static class FooBuilder {
// ...
public Foo build() {
return new Foo(this); // <- this part is what irritates me
}
}
}
Ejemplos también aquí:
- /programming/25130510/builder-pattern-in-java
- https://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html
¿Por qué las personas introducen la fuerte dependencia (mutua) entre el constructor y el tipo para construir?
EDITAR: Quiero decir, sé que por su naturaleza el generador está vinculado a la clase desde la que quiero construir una instancia ( FooBuilder -> Foo
). Lo que cuestiono es: ¿por qué existe la necesidad de lo contrario ( Foo -> FooBuilder
)
Por el contrario, veo (con menos frecuencia) implementaciones que crean una nueva Foo
instancia de Foo
cuándo se crea el generador y establecen los campos en el caso de que se invoquen los métodos de generador apropiados. Me gusta más este enfoque, porque todavía tiene una API fluida y no vincula la clase a su generador. ¿Hay alguna desventaja de este otro enfoque?
Foo
constructor es público?Respuestas:
Se reduce a nunca tener un Foo en un estado medio construido
Algunas razones que me vienen a la mente:
El constructor está vinculado por naturaleza a la clase que está construyendo. Puede pensar en los estados intermedios del constructor como una aplicación parcial del constructor, por lo que su argumento de que está demasiado acoplado no es convincente.
Al pasar todo el generador, los campos en MyClass pueden ser finales, lo que facilita el razonamiento sobre MyClass. Si los campos no son definitivos, podría tener fácilmente acomodadores con fluidez que un constructor.
fuente
El constructor mantendrá campos mutables, establecidos con métodos. La clase real (
Foo
) puede crearfinal
campos inmutables desde el generador.Entonces el Constructor es una clase con estado.
Pero el constructor también podría haber llamado
new Foo(x, y, z)
. Eso sería más unidireccional, mejor estilo en mi humilde opinión. Como entonces, el antipatrón, un campo FooBuilder o similar no sería posible. Por otro lado, FooBuilder garantiza cierta integridad de los datos.Por otro lado, FooBuilder desempeña dos funciones: para construir con una API fluida y para presentar datos al constructor. Es una clase de tipo evento para el constructor. En un código sobrediseñado, los parámetros del constructor podrían mantenerse en algunos FooConstructorParams.
fuente
Porque un "Constructor" se usa típicamente para resolver el "problema del constructor telescópico", especialmente en el contexto de clases inmutables. Vea este enlace para un ejemplo completo.
Considere cómo se verían las alternativas:
O:
Entonces, especialmente para las clases inmutables, si no quieres un constructor con muchos parámetros, en realidad no hay alternativa.
fuente
foo.Attribute1=par1
es posible,Foo
definitivamente es mutable, incluso en Java. Las clases inmutables deben prohibir cualquier mutación de su estado después de la construcción, ni por los colocadores, ni por métodos que muten su estado, ni exponiendo los atributos de los miembros públicos.