Recently I've come across the Builder design pattern. It seems that different authors use "Builder pattern" to refer to different flavours, so let me describe the pattern I'm asking about.
We have an algorithm for creating products, i.e., objects of different types. At a sufficiently high level of abstraction the algorithm is the same for all product types, but each product type requires a different implementation of each of the algorithm's abstract steps. For example, we might have the following cake-baking algorithm:
1. Add liquids. 2. Mix well. 3. Add dry ingredients. 4. Mix well. 5. Pour batter into baking pan. 6. Bake. 7. Return baked cake.
Different cakes would require different implementations of these steps, i.e., what liquids/dry ingredients to use, what speed to mix at, how long to bake, etc.
The pattern says to do it like so. For each product we create a concrete builder class with an implementation for each of the above steps. All of these classes are derived from an abstract builder base class, which is essentially an interface. So, for example, we will have an abstract base class CakeBaker
with pure virtual methods AddLiquid()
, MixLiquids()
, etc. The concrete cake bakers will be concrete subclasses, e.g.,
class ChocolateCakeBaker : public CakeBaker { public: virtual void AddLiquids() { // Add three eggs and 1 cup of cream } virtual void AddDryIngredients() { // Add 2 cups flour, 1 cup sugar, 3 tbsp cocoa powder, // 2 bars ground chocolate, 2 tsp baking powder } ... ... };
The LemonCitrusCakeBaker
would also be a subclass of CakeBaker
, but would use different ingredients and quantities in its methods.
The different cake types will similarly be subclasses of an abstract Cake
base class.
Finally, we have a class to implement the abstract algorithm. This is the director. In the bakery example we might call it ExecutiveBaker
. This class would accept (from the client) a concrete builder object and use its methods in order to create and return the desired product.
Here's my question. Why do we need the director to be separate from the abstract builder? Why not roll them into a single builder abstract base class, making the original abstract builder's public methods protected (and the concrete subclasses override these as before).
Director – The director-class controls the algorithm that generates the final product object. A director object is instantiated and its Construct method is called. The method includes a parameter to capture the specific concrete builder object that is to be used to generate the product.
The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the Builder design pattern is to separate the construction of a complex object from its representation.
Here are key consequences of the Builder pattern: It lets you vary a product's internal representation. The Builder object provides the director with an abstract interface for constructing the product. The interface lets the builder hide the representation and internal structure of the product.
The builder pattern, as the name implies, is an alternative way to construct complex objects. This pattern should be used when we want to build different immutable objects using the same object building process. 3.
The core portion of the Builder pattern concerns the Abstract Builder and its subclasses (concrete builders). According to GoF's Design Patterns, director simply "notifies the builder whenever a part of the product should be built", which can be perfectly done by the client.
The StringBuilder class in the Java API is an example of a builder without the respective director -- typically the client class "directs" it.
Also, in Effective Java and Creating and Destroying Java Objects, Joshua Bloch suggests the use of the builder pattern, and he does not include a director.
The GoF variation of the Builder pattern does NOT have the Builder WITHOUT the Director. There's a different point to this, but I'll explain further.
The Builder pattern's point is to give you multiple ways to create the same object. Builder should only have methods which build different parts of an object, but the algorithm - the way these functions are executed - should be the concern of the Director. Without the Director every client would have the need to know EXACTLY how the building works. But with the Director all the Client needs to know is what Builder to use in a specific case.
So, what we have here are two parts:
Now to the point I was referring earlier. The Builder part of the pattern is useful in other cases and has been used by different vendors WITHOUT the Director for different purposes. A concrete example of such use would be the Doctrine Query Builder.
The disadvantage of such approach is when the Builder starts to build an object it becomes stateful and if the Client doesn't reset the Builder after the object was created - another Client or the same Client that has been used more than once could get the parts of the object that was created earlier. For this reason, Doctrine uses the Factory pattern to create every instance of the Builder.
I hope this helps those googling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With