Difference between builder pattern and constructor

From the Wikipedia page:

The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once

So if I have an object requiring many construction parameters, and those parameters are required in a variety of combinations (thus making some parameters optional) then a builder is a good approach.

e.g. I could create multiple different constructors for an object, or I could do the following:

new ObjectBuilder().withParam1(1).withParam4(4).withParam19(19).build();

thus allowing me to select the parameters required, and not have to define many different constructors. Note also that the above can allow you to populate a builder, and set parameters/call build() multiple times to create a set of related objects easily.


I agree with your view that a Builder is really just a glorified constructor, and that the "builder pattern is just a way to build an object similar to what a constructor does".

However, here are a few of scenarios where the complexity of constructing an object makes the use of a Builder compelling.

Object's dependencies collected over period of time

In Java, StringBuilder is commonly used when building a string over a period of time, or rather, within a complex procedure. For instance, if a server is communicating with a client over a socket, and wants to append some client responses to the string, but not others, and perhaps remove certain responses that were previously appended,the StringBuilder class can be used to do so. At the end of the client/server session, the server can invoke StringBuilder#toString to get the built String.

Lots of parameters

If a constructor has dozens of parameters, it may make the code more readable or easy to maintain to use a builder.

E.g.

new Foo(1,2,3,4,5,6,7,8,9,10,11,12)

Vs.

Foo.newBuilder()
   .bar(1)
   .bar(2)
   .quux(3)
   ...
   .build()

Constructing object graphs

Similar to the "lots of parameters" scenario, I think that the scenario where a builder is most compelling is when constructing a complex object graph. The other answers in this question refer to the telescoping anti-pattern. This scenario (building a complex object graph) can lead to "telescoping", which the Builder helps resolve.

For instance, imagine you have an object-oriented pipeline interface, where a Pipeline depends on Sequence which depends on Stage. A PipelineBuilder would not only provide a nice wrapper around the constructor of Pipeline, but also around the constructors Sequence and Stage, allowing you to compose a complex Pipeline from a single Builder interface.

Instead of telescoping constructors like so:

new Pipeline(
    new Sequence(
        new Stage(
            new StageFunction() {
                public function execute() {...}
            }
        ),
        new Stage(
            new StageFunction() {
                public function execute() {...}
            }
        )
    )
)

A PipelineBuilder would allow you to "collapse" the telescope.

Pipeline.newBuilder()
    .sequence()
        .stage(new StageFunction () {
            public function execute() {...}
        })
        .stage(new StageFunction () {
           public function execute() {...}
        })
    .build()

(Even though I have used indentation in a way that is reflective of the telescoping constructors, this is merely cosmetic, as opposed to structural.)


Building an object in the builder class allows to encapsulate logic related to building an object in one place. Also you can deal more easily with dependencies required to for object construction than using regular constructor.

In other words - if constructing an object is complicated, and there are quite few dependencies - use builder pattern, and if object construction is straightforward (very little logics and just few parameters) - use constructor.