33

Is the "Builder" pattern restricted to addressing the "telescoping constructor" anti-pattern, or can it be said to also address the more general problem of complicated creation of immutable objects?

The StringBuilder class has the word "builder" in its name, but it has nothing to do with telescoping constructors, it simply helps us collect all the data that we need to pass to the constructor of an immutable object.

To me it appears like the answer is a very clear "yes", but there appears to be some disagreement on the topic, so I was hoping that someone could perhaps clarify it.

I was answering this question: Programmers SE: Legitimate “real work” in a constructor? where the OP wants to create a (presumably immutable) object containing a complex tree, and the idea of the "builder" pattern popped up, and while researching it I found this Q&A which seems to say that "StringBuilder" style of object creation is not an application of the "Builder" pattern, for reasons which are not clear to me: Stackoverflow - StringBuilder and Builder Pattern. (Those answering that question failed to make a convincing point as far as I can tell.)

Mike Nakis
  • 32,003
  • 7
  • 76
  • 111
  • 3
    I find Paul Sasik's answer on that Stack Overflow question entirely convincing: StringBuilder is a "workaround" for the performance problem of concatenating immutable strings, nothing more. At best, StringBuilder is "unfortunately named." You could make the argument that StringBuilder can "build" web pages, I suppose, but that's a *specific* application of a *general mechanism.* – Robert Harvey Dec 20 '15 at 15:54
  • @RobertHarvey I only mentioned the StringBuilder in the title in order to conserve space, my focus is not on the StringBuilder per se, but on the more general issue of complex creation of immutable objects, which is a recurring problem. Of course, I don't think there is much room in using the StringBuilder differently. But what I am wondering is whether I have been legitimately calling my classes "builders" in all these cases where I needed a helper to populate a complex structure (usually a tree) to be passed to the constructor of an immutable object. – Mike Nakis Dec 20 '15 at 15:59
  • 3
    Paul Sasik's answer is wrong for Java - I looked at the underlying source code. `StringBuilder` appears to use an underlying character array to represent the String and allows you to do things like insertions and removals at any point. Ultimately, I think that StringBuilder is a workaround for immutable String objects, but it otherwise looks to me like it meets the intent of the Builder pattern. – Thomas Owens Dec 20 '15 at 16:01
  • 4
    I do need to think about this a lot more - it bothers me. I almost started writing up why something like StringBuilder is a version of Builder pattern and everyone else was wrong. But I found a few weaknesses, convinced myself I was wrong, but then managing to get back to my first thought. If you look at just the intent of Builder pattern, it's easy to see that "StringBuilder is a Builder". If you look at the structure of Builder pattern, it's harder. – Thomas Owens Dec 20 '15 at 16:07
  • @ThomasOwens exactly. That's why I thought this might be a good subject for a question, regardless of my predisposition to answer "yes". – Mike Nakis Dec 20 '15 at 16:09
  • 1
    For what it's worth, [this answer on Stack Overflow agrees with my initial thought that StringBuilder is a builder implementation](http://stackoverflow.com/a/1953567/572) and the comments are interesting. So you can find both sides of the argument. I'm favoriting this question - I don't know if I can build a good answer, but it's an interesting question for sure. I'll be thinking about this. – Thomas Owens Dec 20 '15 at 16:11
  • 1
    @RobertHarvey FWIW, the *original* name was `StringBuffer` though that had `synchronized` all over it. –  Dec 20 '15 at 16:12
  • 2
    Not all of the GoF patterns stand the test of time. I'm not *sayin'*, I'm just sayin'. – Ben Dec 20 '15 at 20:14
  • 1
    The Gang of Four doesn't have a copyright on the word "builder." – Karl Bielefeldt Dec 21 '15 at 02:08

1 Answers1

39

A StringBuilder is similar to a the Builder Pattern, but does not share much with the GoF description of this design pattern. The original point of the design pattern was

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

— from Design Patterns, by Gamma, Helm, Johnson, Vlissides.

(note: “complex” primarily means “composed of multiple parts”, not necessarily “complicated” or “difficult”)

The “different representations” is key here. E.g. assuming this construction process:

interface ArticleBuilder {
  void addTitle(String title);
  void addParagraph(String paragraph);
}

void createArticle(ArticeBuilder articleBuilder) {
  articleBuilder.addTitle("Is String Builder an application of ...");
  articleBuilder.addParagraph("Is the Builder Pattern restricted...");
  articleBuilder.addParagraph("The StringBuilder class ...");
}

we might end up with a HtmlDocument or a TexDocument or a MarkdownDocument depending on what concrete implementation is provided:

class HtmlDocumentBuilder implements ArticleBuilder {
  ...
  HtmlDocument getResult();
}

HtmlDocumentBuilder b = new HtmlDocumentBuilder();
createArticle(b);
HtmlDocument dom = b.getResult();

So one central point of the Builder pattern is polymorphism. The Design Patterns book compares this pattern to the Abstract Factory:

Abstract Factory is similar to the Builder in that it too may construct complex objects. The primary difference is that the Builder pattern focuses on constructing a complex object step by step. […] Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.

— from Design Patterns, by Gamma, Helm, Johnson, Vlissides.

This step-by-step aspect has then become the more popular aspect of the Builder pattern, so that in common parlance the Builder pattern is understood like this:

Split construction of an object into multiple steps. This allows us to use named arguments or optional parameters even in languages that do not support these features.

Wikipedia defines the pattern like this:

The builder pattern is an object creation software design pattern. Unlike the abstract factory pattern and the factory method pattern whose intention is to enable polymorphism, the intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern[citation needed]. […]

The builder pattern has another benefit. It can be used for objects that contain flat data (html code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited. This type of data cannot be edited step by step and must be edited at once. The best way to construct such an object is to use a builder class.[citation needed]

— from Builder Pattern on Wikipedia, by various contributors.

So as we can see, there is no truly common understanding of which pattern this name refers to, and in some points different definitions even contradict one another (e.g. regarding the relevance of polymorphism for Builders).

The only common property of the StringBuilder with various interpretations of the pattern is that the product is created step by step rather than in one go. It does not meet a strict reading of the GoF definition of the design pattern, but please note that design patterns are malleable concepts meant to facilitate communication. I would continue to call StringBuilder an example of the Builder Pattern, albeit an atypical one – the main reason for that structure in Java is performant concatenation in the presence of immutable strings, but not some interesting object-oriented design.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
amon
  • 132,749
  • 27
  • 279
  • 375
  • 7
    It seems to me that creating immutable objects seems to be one of the more common uses of Builders - I think this has replaced the primary use as described by GoF, so agree that this is definitely best described as an instance of the pattern. – Jules Dec 21 '15 at 16:16
  • Agree with usage in creating immutable graphs, Another usecase for Builder DSLs are really useful for creating large graphs of Fake data / ObjectMothers during Unit + Integration Testing. – StuartLC Apr 07 '16 at 11:47