Recentemente, comecei a ler Java eficaz por Joshua Bloch. Achei a idéia do padrão Builder [Item 2 do livro] realmente interessante. Tentei implementá-lo no meu projeto, mas houve erros de compilação. A seguir, é essencialmente o que eu estava tentando fazer:
A classe com vários atributos e sua classe de construtor:
public class NutritionalFacts {
private int sodium;
private int fat;
private int carbo;
public class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder(int s) {
this.sodium = s;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
Classe em que tento usar a classe acima:
public class Main {
public static void main(String args[]) {
NutritionalFacts n =
new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
}
}
Estou recebendo o seguinte erro do compilador:
é necessária uma instância anexa que contenha java.BuilderPattern.NutritionalFacts.Builder eficazFacts Nutritional n = new NutritionalFacts.Builder (10) .carbo (23) .fat (1) .build ();
Eu não entendo o que a mensagem significa. Por favor explique. O código acima é semelhante ao exemplo sugerido por Bloch em seu livro.
java
design-patterns
builder-pattern
Swaranga Sarma
fonte
fonte
Respostas:
Faça do construtor uma
static
classe. Então vai funcionar. Se não for estático, exigiria uma instância de sua classe proprietária - e o objetivo é não ter uma instância dela e até proibir a criação de instâncias sem o construtor.Referência: Classes Aninhadas
fonte
Builder
estástatic
no exemplo do livro (página 14, linha 10 na 2ª Edição).Você deve tornar a classe Builder como estática e também tornar os campos finais e ter getters para obter esses valores. Não forneça setters para esses valores. Dessa forma, sua classe será perfeitamente imutável.
E agora você pode definir as propriedades da seguinte maneira:
fonte
final
Os campos só fazem sentido se os campos forem sempre necessários durante a inicialização. Caso contrário, os campos não devem serfinal
.Você está tentando acessar uma classe não estática de maneira estática. Mude
Builder
parastatic class Builder
e deve funcionar.O exemplo de uso que você fornece falha porque não há instância do
Builder
presente. Uma classe estática para todos os fins práticos é sempre instanciada. Se você não o tornar estático, precisará dizer:Porque você precisaria construir um novo
Builder
sempre.fonte
Para gerar um construtor interno no Intellij IDEA, confira este plugin: https://github.com/analytically/innerbuilder
fonte
Você precisa declarar a
Builder
classe interna comostatic
.Consulte alguma documentação para classes internas não estáticas e classes internas estáticas .
Basicamente, as instâncias de classes internas não estáticas não podem existir sem a instância de classe externa anexada.
fonte
Depois de ter uma idéia, na prática, você pode achar o lombok's
@Builder
muito mais conveniente.@Builder
permite que você produza automaticamente o código necessário para que sua classe seja instanciada com códigos como:Documentação oficial: https://www.projectlombok.org/features/Builder
fonte
Isso significa que você não pode criar um tipo de anexo. Isso significa que primeiro você precisa selecionar uma instância da classe "pai" e, a partir dessa instância, você pode criar instâncias de classe aninhadas.
Classes aninhadas
fonte
A classe Builder deve ser estática. No momento, não tenho tempo para testar o código além disso, mas se não funcionar, avise-me e darei outra olhada.
fonte
Pessoalmente, prefiro usar a outra abordagem, quando você tem 2 classes diferentes. Então você não precisa de nenhuma classe estática. Isso é basicamente para evitar a gravação
Class.Builder
quando você precisar criar uma nova instância.Portanto, você pode usar seu construtor assim:
fonte
Como muitos já declarados aqui, você precisa fazer a aula
static
. Apenas uma pequena adição - se você quiser, existe uma maneira um pouco diferente sem a estática.Considere isto. Implementar um construtor declarando algo como
withProperty(value)
setters de tipo dentro da classe e fazê-los retornar uma referência a si mesma. Nessa abordagem, você tem uma classe única e elegante, que é um segmento seguro e conciso.Considere isto:
Confira mais exemplos do Java Builder .
fonte
Você precisa alterar a classe Builder para a classe estática Builder . Então vai funcionar bem.
fonte