8

Often I see the implementation of the builder pattern (in Java) to be like this:

public class Foo {
    private Foo(FooBuilder builder) {
        // get alle the parameters from the builder and apply them to this instance
    }

    public static class FooBuilder {
        // ...
        public Foo build() {
            return new Foo(this); // <- this part is what irritates me
        }
    }
}

Examples also here:

Why do people introduce the strong (mutual) dependency between builder and type to build?

EDIT: I mean, I know that by its nature the builder is tied to the class I want to build an instance from (FooBuilder -> Foo). What I questioning is: why is there the necessity for the other way around (Foo -> FooBuilder)

On the contrary I see (less often) implementations that create a new instace of Foo when the builder is created and set the fields on the instance of Foo when the appropriate builder-methods are called. I like this approach better, because it still has a fluent API and does not tie the class to its builder. Is there any downside of this other approach?

Andy
  • 1,305
  • 7
  • 13
  • Does your question also apply if `Foo` constructor is public ? – Spotted Sep 28 '16 at 10:50
  • 1
    The reason is DRY. If you have many fields they would have to be repeated in the constructor of Foo if Foo does not know about FooBuilder. This way you save the constructor of Foo. – Esben Skov Pedersen Sep 28 '16 at 11:43

3 Answers3

8

It boils down to never having a Foo in a half constructed state

Some reasons that spring to mind:

The builder's is by nature tied to the class it is constructing. You can think of the intermediate states of the builder as partial application of the constructor, so your argument that it is too coupled isn't persuasive.

By passing the whole builder in, fields in MyClass can be final, making reasoning about MyClass easier. If the fields are not final, you could just as easily have fluent setters than a builder.

Caleth
  • 10,519
  • 2
  • 23
  • 35
  • 1. by its nature the builder is tied to the class I want to build an instance from (FooBuilder -> Foo). What I questioning is: why is there the necessity for the other way around (Foo -> FooBuilder) 2. I see the point with the _final_ modifier, but besides that modifier, the FooBuilder can simply set the fields of Foo (even if they are private, because FooBuilder is part of Foo), and if i don't create setters, the instance is still immutable, isn't it? – Andy Sep 28 '16 at 09:32
  • It boils down to *never* having a Foo in a half constructed state, even if it is only ever internal to the builder. Would you think it a problem that in a class with a large overload set of constructors, there was a "strong (mutual) dependency" between the constructors and the rest of the class? Because that's what a Builder is - a concise way of expressing lots of similar constructors – Caleth Sep 28 '16 at 09:40
  • Thanks for the answer (about never having an inconsistent state), that makes it clear. I don't like the answer but I understand it now. When you incorporate that in you answer, I will accept it. – Andy Sep 28 '16 at 10:42
3

The builder will hold mutable fields, set with methods. The actual class (Foo) can then create immutable final fields from the builder.

So the Builder is a stateful class.

But the builder could alse have called new Foo(x, y, z). That would be more one-directional, better style IMHO. As then the anti-pattern, a FooBuilder field or such would not be possible. On the other hand the FooBuilder guarantees some integrity of the data.

On the other hand FooBuilder plays two roles: for building with a fluent API, and for presenting data to the constructor. It is an event-type class for the constructor. In a overdesigned code the constructor params could be kept in some FooConstructorParams.

Joop Eggen
  • 2,011
  • 12
  • 10
2

Because a "Builder" is typically used to solve the "telescoping constructor problem", especially in context of immutable classes. See this link for a full-fledged example.

Consider what the alternatives would look like:

 public static class FooBuilder {
    // works with immutable classes, but leads to telescoping constructor
    public Foo build() {
        return new Foo(par1, par2, par3, ....); 
    }
 }

Or:

 public static class FooBuilder {
    // does not work for immutable classes:
    public Foo build() {
        var foo = new Foo(); 
        foo.Attribute1=par1;
        foo.Attribute2=par2;
        //...
        return foo;
    }
 }

So especially for immutable classes, if you want no constructor with a bunch of parameters, there is actually no alternative.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • I know what problem the builder pattern solves. But you didn't answer my question why the *implementation* often looks like the example given. Even Josh Bloch in the article you linked does not. However, Caleth does in his/her comment. – Andy Sep 28 '16 at 10:40
  • @Andy: I gave an example to clarify why this answers your question. – Doc Brown Sep 28 '16 at 11:27
  • Actually, your second example is not necessarily mutable. If you do not implement setter-methods it's *immutable*. But I now see, where you are heading at. – Andy Sep 28 '16 at 11:32
  • @Andy: I could actually rewrite the example using setters if you prefer Java idioms instead of C# idioms. But if `foo.Attribute1=par1` is possible, `Foo` is definitely mutable, even in Java. Immutable classes need to forbid any mutation of their state after construction, neither by setters, nor by methods mutating their state, nor by exposing public member attributes. – Doc Brown Sep 28 '16 at 11:35
  • "So especially for immutable classes".... But a class without setters will still appear immutable from the outside. Whether they are final or not is a nice-to-have. – Esben Skov Pedersen Sep 28 '16 at 11:37
  • @EsbenSkovPedersen: yes, so what? – Doc Brown Sep 28 '16 at 11:39
  • So your last paragraph is not actually correct since you could just not have the fields be final but still immutable by omitting mutators – Esben Skov Pedersen Sep 28 '16 at 11:47
  • @EsbenSkovPedersen: where in my answer did I write something about using "final"? – Doc Brown Sep 28 '16 at 16:07
  • You imply it in the comment: "does not work for immutable classes" – Esben Skov Pedersen Sep 29 '16 at 03:35
  • @EsbenSkovPedersen: well, it seems *you* imply something which I am not aware of. An immutable class is by definition one which does not provide any public method to alter its state after construction. Don't know from where you come to the conclusion I would have written something about using "final": – Doc Brown Sep 29 '16 at 06:27