user14647130
user14647130

Reputation:

What is the advantage of adding a static "builder()" method in the Builder Pattern?

I'm wondering about whether my implementation of the Builder pattern is wrong or not.
Let's say we have a User class for which we want to have a Builder, my implementation would be:

public class User
{
    private final String name;
    private final int age;
        
    private User(Builder builder)
    {
        this.name = builder.name;
        this.age = builder.age;
    }  
       
    public static class Builder
    {
        //blah blah
            
        public User build()
        {
            return new User(this);
        }
    }
}

But from time to time, I see that some people add this method:

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

for seemingly no reason other than achieving a slightly more readable syntax:

//Before
User user = new User.Builder()
    .named("Tester")
    .build();

//After
User user = User.builder()
    .named("Tester")
    .build();

Is this the only advantage? Do I miss anything?

Upvotes: 2

Views: 78

Answers (1)

Ralf Kleberhoff
Ralf Kleberhoff

Reputation: 7290

Regarding your initial question:

whether my implementation of the Builder pattern is wrong or not

IMHO, your code uses incorrect dependencies.

Your User class has to know about the Builder's internals in

private User(Builder builder)
{
    this.name = builder.name;
    this.age = builder.age;
}

It should be the other way round: the Builder should know about the User's construction requirements. The User class should not even know that there are any builders that can help in the construction.

So, I'd refactor this to become

public class User
{
    private final String name;
    private final int age;
        
    private User(String name, int age)
    {
        this.name = name;
        this.age = age;
    }  
       
    public static class Builder
    {
        //blah blah
            
        public User build()
        {
            return new User(name, age);
        }
    }
}

Regarding the static builder() method:

You always introduce classes and methods as domain-specific extensions of the Java language, allowing your vallers to write application code using that new vocabulary.

The question always is: "Does your new vocabulary make things easier for the callers of your class?"

So, how would you like to create a User in your application-specific language? Some possibilities:

  • new User("Tester", 42); This can become quite unclear in case of more than two parameters, lacks flexibility.
  • User.withNameAndAge("Tester", 42); This forces you to provide many similar static methods.
  • User.builder().named("Tester").aged(42).build(); This reads as if you want to give a name to the builder, not the user.
  • new User.Builder().named("Tester").aged(42).build(); This reads as if you want to give a name to the builder, not the user.
  • User.named("Tester").aged(42).build(); This is nice to read, but a bit complex to implement
  • new User().named("Tester").aged(42); This is nice to read, but runs the risk of incomplete initialization.

Decide what you find best (regarding readability, flexibility, robustness, ...) and then implement it. For some creation styles you'll need a Builder class, for others it might be helpful under the hood, and for others it's not necessary.

Upvotes: -3

Related Questions