Muitas vezes, vejo a implementação do padrão do construtor (em Java) assim:
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
}
}
}
Exemplos também aqui:
- /programming/25130510/builder-pattern-in-java
- https://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html
Por que as pessoas introduzem a forte dependência (mútua) entre construtor e tipo a construir?
EDIT: Quero dizer, eu sei que, por sua natureza, o construtor está vinculado à classe da qual quero criar uma instância a partir de ( FooBuilder -> Foo
). O que eu questiono é: por que existe a necessidade de o contrário ( Foo -> FooBuilder
)
Pelo contrário, vejo (com menos frequência) implementações que criam uma nova instância de Foo
quando o construtor é criado e configuram os campos na instância de Foo
quando os métodos de construtor apropriados são chamados. Eu gosto mais dessa abordagem, porque ela ainda possui uma API fluente e não vincula a classe ao seu construtor. Existe alguma desvantagem dessa outra abordagem?
Foo
construtor for público?Respostas:
Tudo se resume a nunca ter um Foo em um estado meio construído
Alguns motivos que vêm à mente:
O construtor está por natureza vinculado à classe que está construindo. Você pode pensar nos estados intermediários do construtor como aplicação parcial do construtor, portanto, seu argumento de que ele é muito acoplado não é convincente.
Ao passar o construtor inteiro para dentro, os campos no MyClass podem ser finais, facilitando o raciocínio sobre o MyClass. Se os campos não forem finais, você poderia facilmente ter setters fluentes do que um construtor.
fonte
O construtor manterá campos mutáveis, configurados com métodos. A classe real (
Foo
) pode criarfinal
campos imutáveis a partir do construtor.Portanto, o Builder é uma classe com estado.
Mas o construtor também poderia ter chamado
new Foo(x, y, z)
. Isso seria mais IMHO unidirecional e melhor. Como então o anti-padrão, um campo FooBuilder ou outro não seria possível. Por outro lado, o FooBuilder garante alguma integridade dos dados.Por outro lado, o FooBuilder desempenha duas funções: criar com uma API fluente e apresentar dados ao construtor. É uma classe de tipo de evento para o construtor. Em um código com excesso de design, os parâmetros do construtor podem ser mantidos em alguns FooConstructorParams.
fonte
Como um "Construtor" é normalmente usado para resolver o "problema do construtor telescópico", especialmente no contexto de classes imutáveis. Veja este link para um exemplo completo.
Considere como seriam as alternativas:
Ou:
Portanto, especialmente para classes imutáveis, se você não deseja um construtor com vários parâmetros, na verdade não há alternativa.
fonte
foo.Attribute1=par1
possível,Foo
é definitivamente mutável, mesmo em Java. Classes imutáveis precisam proibir qualquer mutação de seu estado após a construção, nem por levantadores, nem por métodos que mutam seu estado, nem expondo atributos de membros públicos.