有效的Java中的生成器模式

我最近开始阅读Joshua Bloch的Effective Java。 我发现Builder模式的想法(书中的第2项)真的很有趣。 我试图在我的项目中实现它,但有编译错误。 以下是我正在尝试做的事情:

具有多个属性的类及其构build器类:

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; } } 

我尝试使用上面的类的类:

 public class Main { public static void main(String args[]) { NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build(); } } 

我收到以下编译器错误:

一个包含effectivejava.BuilderPattern.NutritionalFacts.Builder的封闭实例需要营养成分n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build();

我不明白这信息是什么意思。 请解释。 上面的代码与Bloch在他的书中提出的例子类似。

使build设者成为一个static类。 然后它会工作。 如果它是非静态的,它将需要它自己的类的一个实例 – 而且重点不在于它的一个实例,甚至禁止在没有构build器的情况下创build实例。

 public class NutritionFacts { public static class Builder { } } 

参考: 嵌套类

你应该让Builder类成为静态的,你也应该让这些字段成为final,并让getter得到这些值。 不要为这些值提供setter。 通过这种方式,你的类将是完全不可变的。

 public class NutritionalFacts { private final int sodium; private final int fat; private final int carbo; public int getSodium(){ return sodium; } public int getfat(){ return fat; } public int getCarbo(){ return carbo; } public static class Builder { private int sodium; private int fat; private int carbo; public Builder sodium(int s) { this.sodium = s; return this; } 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; } } 

现在你可以设置属性如下:

 NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15). fat(5).build(); 

您正在尝试以静态方式访问非静态类。 改变Builderstatic class Builder ,它应该工作。

您提供的示例用法失败,因为不存在Builder实例。 所有实际目的的静态类总是被实例化。 如果你不把它变成静态的,你需要说:

 Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build(); 

因为你每次都需要构build一个新的Builder

要在Intellij IDEA中生成内部构build器,请查看以下插件: https : //github.com/analytical/innerbuilder

你需要声明Builder内部类是static

请参阅非静态内部类和静态内部类的一些文档。

基本上,没有附加的外部类实例,非静态内部类实例不能存在。

生成器类应该是静态的。 现在我没有时间去实际testing代码,但如果它不起作用,请让我知道,我会再看看。

这意味着你不能创build封闭types。 这意味着首先你必须cerate一个“父”类的实例,然后从这个实例中,你可以创build嵌套的类实例。

 NutritionalFacts n = new NutritionalFacts() Builder b = new n.Builder(10).carbo(23).fat(1).build(); 

嵌套类