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

时间:2015-05-22 12:02:11

标签: java object builder

我已经构建了(使用Builder Pattern)一个包含三个字段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;
    }
}

现在,在以下类中,我构建了我的Employee对象,

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"打破已经建立的员工对象?

仅供参考:我不想在Setters对象中添加Employee

5 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:2)

使用Copy-On-Write构建另一个(重用现有字段但更改年龄)。

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

请记住,这将是另一个目标。

答案 2 :(得分:2)

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

我想出了一个解决方案,所以大约5年后,这就是我的回答大声笑(要到这里就结束了)

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

这个实例声明是故意的,因为我打算在内部创建它,或者要从外部请求它的内存。

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

答案 3 :(得分:1)

如果您不想放置setter(并使Employee变为可变),则无法修改john的年龄...而不是这样,您可以做的是:

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

答案 4 :(得分:0)

如果您不想要setter或public non-final字段,那么您可以向构建器添加一个额外的构造函数,这将导致初始状态与实例匹配,但可以使用构建器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();