Update: Without fluent interface, builder pattern can still be done, see my implementation.
Edit for possible duplication issues:
When should the builder design pattern be used?: My question is about the actual advantages of Builder Pattern(of GoF). And the chosen answer in the link is about Bloch Builder, which may(See @amon 's answer) or may not be a pattern.
Design Patterns are NOT for solving a specific problem(telescoping constructor or so). See reference.
So, what make something be a pattern? (The LHS are what pointed out by John Vlissides. The RHS my opinion.)
Recurrence. (A pattern should be general, so it can be applied to many problems.)
Teaching. (It should let me know how to improve my current solution scenario.)
It has a name. (For more effective conversation.)
Reference: Pattern Hatching: Design Patterns Applied written by John Vlissides. Chapter one: common mis-understandings about design patterns, if I remember.
GoF's implementation of Builder in real life: You can read this answer before reading my notes about builder pattern. It's a great answer, but still, it doesn't solve my questions. And the title is not related.
UML of Builder Pattern:
I've read the book of GoF about builder pattern again and again, the followings are some of my notes:
- A director can be reused.
- And it contains the algorithm(s) to build a product, step by step.
- Use the interface provided by Builder.
- Logically, it create the product.
- A builder should be general enough (to let almost any possible different ConcreteBuilder to build their corresponding product. This is the origin of my second question below.)
- A concrete builder builds all the parts needed, and know how to assemble them.
- And keeps track of its product. (It contains a reference of its product.)
- Client get their final product from a concrete builder. (It's ConcreteBuilder who has the getProduct() method, Builder don't have getProduct() (abstract) method.)
- It's the complex object to be built. For every ConcreteBuilder, there is a corresponding Product. (This is the origin of my first question below.)
And it provide the interface for its corresponding concrete builder to build the logical parts and to assemble them.
This is why people confused about Bloch builder and builder pattern of GoF. Bloch builder just makes the interface easier to be used by the concrete builder. (Btw, how to indent this line...)
The client :
- Choose a concrete builder he needs. (Implementor)
- And choose a director he needs. (Logic)
- Then inject the concrete builder into the director.
- Call director's construct() method.
- Get the product by calling getProduct() of concrete builder.
It takes me a lot of effort to remember all these rules, but I have some questions:
If the Product is complex enough, it should be a bad design.
Ok, if you say it's not a bad design. So how can you design the Builder interface to satisfy any ConcreteProduct?
The followings are advantages of the Builder Pattern for me:
The Scope: A ConcreteBuilder constrains all components it needs in the same scope. So the client of the Builder don't see anything about/related to Product.
Less Parameters in Builder: Since all the methods inside the ConcreteBuilder can share those variables, the methods of ConcreteBuilder should be easier to read and write. (From the book Clean Code, the more parameters a method has, the worse.)
Dependency Inversion Principle: The Builder interface plays a key role in the builder pattern. Why? Because now both Director(the logic) and ConcreteBuilder(the implementation) follow the same rule to build a thing.
After all, I'm not sure. I need the actual answer.
I appreciate any different perspectives about what is a builder pattern. Different people will have different definition of their own, but here I'm talking about Builder Pattern of GoF. So please read carefully.
But people there pointed out that it's not a Builder Pattern. Like @Robert Harvey, I disagreed about it. So I come here for the real answer.