Effective Java 中的构建器模式

新手上路,请多包涵

我最近开始阅读 Joshua Bloch 的《Effective Java》。我发现 Builder 模式 [书中的第 2 项] 的想法非常有趣。我试图在我的项目中实现它,但出现编译错误。以下本质上是我试图做的事情:

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

 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 的封闭实例 NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build();

我不明白消息的意思。请解释。上面的代码类似于 Bloch 在他的书中建议的示例。

原文由 Swaranga Sarma 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 607
2 个回答

使生成器成为 static 类。然后它会起作用。如果它是非静态的,它将需要它所属类的实例——关键是不要拥有它的实例,甚至禁止在没有构建器的情况下创建实例。

 public class NutritionFacts {
    public static class Builder {
    }
}

参考: 嵌套类

原文由 Bozho 发布,翻译遵循 CC BY-SA 2.5 许可协议

您应该将 Builder 类设置为静态的,还应该将字段设置为 final 并使用 getter 来获取这些值。不要为这些值提供设置器。这样你的类将是完全不可变的。

 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();

原文由 Raj Hassani 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题