使用Builder Pattern构建对象时,如何修改Java中已经构建的对象?

How to modify the already built object in Java, when the Object is built using Builder Pattern?

我已经构建(使用 Builder 模式)一个具有三个字段 NameAgeGender 的 Employee 对象。

public class Employee {

    private String name;
    private String age;
    private String gender;

    // Constructor
    private Employee(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.gender = builder.gender;
    }

    // Employee Builder
    public static class Builder {
        private String name;
        private String age;
        private String gender;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder age(String age) {
            this.age = age;
            return this;
        }

        public Builder gender(String gender) {
            this.gender = gender;
            return this;
        }
    }

    // Getters
    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }

    public String getGender() {
        return gender;
    }
}

下面Class我已经构建了我的员工对象,

public class TestEmployee {

    public static void main(String[] args) throws IOException {
        Employee employee = new                Employee.Builder().age("23").gender("Male").name("John").build();

        System.out.println("Name : " + employee.getName());
        System.out.println("Age : " + employee.getAge());
        System.out.println("Gender : " + employee.getGender());
    }
}

如何通过破坏已经构建的员工对象来修改员工的年龄"John"?

仅供参考:我不想在我的 Employee 对象中包含 Setters

您想修改一个不可变对象。你看到那里的问题了吗?

要么添加 setter(或任何改变状态的方法),要么接受对象是不可变的。

您当然可以根据旧对象的值创建一个新对象,但那样它就不是同一个对象了。

如果您不想放置 setter(并使 Employee 可变),则不能修改 john 的年龄...除此之外,您可以做的是:

employee = new Employee.Builder()
                       .age("21")
                       .gender(employee.getGender())
                       .name(employee.getName())
                       .build();

使用写时复制构建另一个(重用现有字段但更改年龄)。

Employee.Builder()
     .age(employee.getAge() + 1)
     .gender(employee.getGender())
     .name(employee.getName())
     .build();

记住,这将是另一个对象。

如果您不需要 setter 或 public 非最终字段,则可以向构建器添加一个额外的构造函数,这将导致初始状态与实例匹配,但构建器 setter 可用。这不会修改原始对象,而是基于它创建一个新对象。

public static class Builder {
    private String name;
    private String age;
    private String gender;

    public Builder(Employee employee) {
        this.name = employee.getName();
        this.age = employee.getAge();
        this.gender = employee.getGender();
    }

    public Builder name(String name) {
        this.name = name;
        return this;
    }

    public Builder age(String age) {
        this.age = age;
        return this;
    }

    public Builder gender(String gender) {
        this.gender = gender;
        return this;
    }

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

然后您可以按如下方式使用它。

Employee employee = new Employee.Builder().age("23").gender("Male").name("John").build();
Employee employee2 = new Employee.Builder(employee).name("Jane").build();

啊我也试图用这种方法解决我的问题,具有讽刺意味的是我偶然发现了这个问题。我理解这里的挑战,我们正在尝试修改具有相同构建器设置器的对象,但这样做我们最终会得到一个新对象。

我发现有一个解决方案,所以在大约 5 年后,这是我的答案,哈哈(给那些会在这里结束的人)

首先,不要在内部静态生成器中创建 OuterClass 的重复属性 class。 *在 Builder class 中声明一个 outer class 的实例。这意味着您的 build() 方法将 return 该实例。

此*实例声明是有意的,因为我计划在内部创建它或从外部请求它的内存。

public class Employee {

    private String name;
    private String age;
    private String gender;


    public Static Builder builder()
    {
       return new Builder();
    }

    public Static Builder modifier(Employee employee)
    {
       return new Builder(employee);
    }


    // Employee Builder
    public static class Builder {
        private Employee employee;

        public Builder(Employee employee)
        {
           this.employee = employee;
        } 

        public Builder()
        {
           this.employee = new Employee();
        }

        public Builder name(String name) {
            this.employee.name = name;
            return this;
        }

        public Builder age(String age) {
            this.employee.age = age;
            return this;
        }

        public Builder gender(String gender) {
            this.gender = gender;
            return this;
        }

        public Employee build()
        {
           return this.employee;
        }
    }

    // Getters
    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }

    public String getGender() {
        return gender;
    }
}

注意这里的调整,我引入了一个修饰符,它接受 Employee 对象并进一步允许客户端使用 Builder 模式修改它。 所以你的客户会像这样使用它...

创建新员工

Employee employee = Employee.builder().name("abc).age(20).build();

修改同一个实例

Employee.modifier(employee)
        .name("xyz")
        .build();