Using the right builder in the right place

I am very interested in the build pattern, I use it a lot, but I am not sure if the creators I make are good enough, and I also doubt the whole environment where I can use them. This is an example of how I am creating a constructor:

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 example of use:

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

      

Here are some of my doubts:

  • Do you think this is really immutable? If not, how can I improve it?
  • About thread safety. This is probably my main doubt. Is it really thread safe? I have seen examples on the internet that say that class level variables should be final and passed through the constructor. I also saw one example where variables were declared volatile. What do you think about this?
  • Do you think this builder will have any limitation as to the scenario in which it can be used? I mean, would it make sense to have it called either in an EJB and a JSF backing bean, either in an MDB or as a JPA object ...?
+3


source to share


1 answer


Do you think this is truly immutable? [...] Is it really thread safe?

No part of your code can be immutable. It also likely hinders thread safety; that it was very difficult to declare that the class is or is not binary thread safe. I also don't understand why you ever shared the linker instances between threads, but I might be confusing the simplicity of your example code.

To ensure thread safety, yours Builder

must be immutable. This means that each method withXXX()

must return a new builder that represents the new state. (There are probably smarter ways to do this, but this would be a simpler approach.)



Just to reiterate, I'm not sure if this is absolutely necessary to make the builder thread safe - most of the time these are objects with very short lifespan and visibility. If you want to make them immutable depends on the use case, you may want to keep partially filled builders, but this is also somewhat rare. (Subjectively, this, however, seems more intuitive for a method whose name begins with with

, so as not to modify the object in place, rather than the one whose name begins with set

.)

Do you think this builder will have some kind of limitation as to the scenario in which it can be used?

This is generally irrefutable, but if you make your objects Person

immutable and therefore only constructive for your builder they will not be usable as JPA objects, I think this is also JSF beans support. Java frameworks that create or manipulate specific objects for you most often do not assume they are JavaBeans, which means that those objects can be created by calling the no-args constructor and properties that create the reflection.

+1


source







All Articles