3

I very interested in the builder pattern, I use it often but I am not sure if the builders I make are good enough and also I have doubts about all the surroundings where I can use them. This is an example of how I create a builder:

public class Person {

    private String name;
    private String secondName;
    private int age;

    public static class Builder {
        private boolean isBuilt;
        private Person person = new Person();

        private void check() {
            if (isBuilt) {
                throw new IllegalStateException(
                        "The object cannot be modified after built");
            }
        }

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

        public Builder withSecondName(String secondName) {
            check();
            person.secondName = secondName;
            return this;
        }

        public Builder withAge(int age) {
            check();
            person.age = age;
            return this;
        }

        public Person build() {
            check();
            isBuilt = true;
            return person;
        }
    }

    @Override
    public String toString() {
        return "Name: " + name + "\nSecond name:" + secondName + "\nAge:" + age;
    }
}

Just a quick usage example:

Person person = new Person.Builder()
        .withName("John")
        .withSecondName("Smith")
        .withAge(50)
        .build();
        System.out.println(person);

Here some of my doubts:

  • Do you think it is really immutable?If no, How can I improve it?
  • About thread safety. Well this is probably my main doubt. Is this really thread safe? I saw examples on the internet that say that the class level variables must be final and passed via a constructor. Also I saw one example where the variables were declared as volatile. What do you think about it?
  • Do you think that this builder would have any limitation in what regards the scenario where it can be used? What I mean is would it be suitable to be called in either an EJB, a JSF backing bean, an MDB,or become a JPA entity...?
4

1 回答 1

1

你认为它真的是一成不变的吗?[...] 这真的是线程安全的吗?

您的代码中没有任何部分是不可变的。这也可能会妨碍线程安全;也就是说,很难以二进制方式声明一个类是否是线程安全的。我也不明白为什么你会首先在线程之间共享构建器实例,但我可能会被你的代码示例的简单性误导。

为了更容易实现线程安全,您Builder的 s 本身应该是不可变的。这意味着每个withXXX()方法都应该返回一个代表新状态的新构建器。(可能有更聪明的方法可以做到这一点,但那将是直接的方法。)

只是重申一下:我不确定是否有必要使构建器线程安全 - 大多数情况下它们是生命周期和可见范围非常短的对象。是否要使它们不可变取决于用例,您可能希望存储部分填充的构建器,但这也很少见。with(但主观上,对于名称以 开头的方法而言,不就地修改对象似乎更直观,而不是名称以 开头的方法set。)

你认为这个构建器在它可以使用的场景方面有什么限制吗?

这通常是无法回答的,但是如果您确实使您的Person对象不可变,因此只能由您的构建器构造,它们将无法用作 JPA 实体,我的猜测也是作为 JSF 支持 bean。Java 框架通常会为您创建/管理某些对象,而不是期望它们是 JavaBean,这意味着可以通过反射调用无参数构造函数和属性设置器来创建这些对象。

于 2013-02-10T23:47:45.053 回答