Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不可变对象生成器_Java_Builder - Fatal编程技术网

Java 不可变对象生成器

Java 不可变对象生成器,java,builder,Java,Builder,将构建器实例存储在它所构建的实例中是否被认为是一种良好的做法?问题是,我经常发现自己处于一种情况,当我需要创建一个与我已经拥有的对象非常相似的对象时。假定该对象有许多8-10个字段。通常,对于可变对象,我会使用setter 例如,让我们以经典的Bloch'sNutricinfacts为例: public class NutritionFacts { private final int servingSize; private final int servings; pri

将构建器实例存储在它所构建的实例中是否被认为是一种良好的做法?问题是,我经常发现自己处于一种情况,当我需要创建一个与我已经拥有的对象非常相似的对象时。假定该对象有许多8-10个字段。通常,对于可变对象,我会使用setter

例如,让我们以经典的Bloch's
Nutricinfacts
为例:

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    private final Builder builder;

    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values
        private int calories = 0;
        private int fat = 0;
        private int carbohydrate = 0;
        private int sodium = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }
        public Builder calories(int val)
        { calories = val; return this; }
        public Builder fat(int val)
        { fat = val; return this; }
        public Builder carbohydrate(int val)
        { carbohydrate = val; return this; }
        public Builder sodium(int val)
        { sodium = val; return this; }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
        this.builder = builder;
    }
}
我对它进行了一些修改,以便将来如果我想制作simmiliar副本,可以访问builder实例


您认为如何?

如果重用
生成器来构建第二个实例,会发生什么?第一个实例中的
Builder
将生成与第二个实例类似的实例。可能不是你所期望的

我建议使用模板实例创建
Builder

    public Builder(NutritionFacts template) {
        this.servingSize = template.getServingSize();
        ...
    }

或者您可能有一个clone方法。@dystroy clone不是一个好选项,因为类处于不可变状态,并且克隆将与第一个实例完全相同,而无需修改。ante的答案可能是正确的,也就是说,不,您不应该在构建类中引用生成器。不可变对象的关键在于它是不可变的。引用一个可到达的可变对象会使您假定不可变对象是可变的。如果两个线程开始使用同一个构建器执行不同的操作,该怎么办?您以前使用的线程安全的不可变对象现在不是线程安全的。我真的很困惑,我没有偶然发现这样一个用例,或者标准构建器模式没有提供以模板对象为参数的构造函数。我广泛使用它。一直以来,我都需要创建一个与我已经拥有的对象相似的对象。从DBMS中获取一些对象,然后设置一些标志并将其持久化,这不是一种常见的做法吗?