top of page
Writer's pictureSunil Kumar Yadav

Builder: Must Know Design Pattern (2/7)



In my last article, I discussed the Factory design pattern. Key disadvantages of the Factory method patterns were 1. the high number of required classes, 2. the user has less control over created objects and 3. the extension of the application is very elaborate.


We can avoid the above issues of the Factory method by using the Builder pattern.


What is a Builder pattern?

Builder is a part of Gang of Four design pattern and it is categorized under creational design patterns. The builder pattern is designed to provide a flexible solution to 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. In the Builder pattern objects are created in step by step manner, providing more control to the user/client on created objects.


Builder patterns separate the construction of a complex object from its representation so that the same construction process can create different representations. Let's try to understand the Builder pattern using our earlier example of the burger factory. In the Factory method, we did not have full control of the final burger as the types of burgers were fixed with no scope of customization.


In the below example, we have a Burger class with various methods to add the bun, patty, and cheese. The BurgerBuilder class is used by the user/client to create the final Burger object with the required customization.

class Burger:
    def __init__(self):
        self.buns = None
        self.patty = None
        self.cheese = None

    def setBuns(self, bunStyle):
        self.buns = bunStyle

    def setPatty(self, pattyStyle):
        self.patty = pattyStyle

    def setCheese(self, cheeseStyle):
        self.cheese = cheeseStyle

class BurgerBuilder:
    def __init__(self):
        self.burger = Burger()

    def addBuns(self, bunStyle):
        self.burger.setBuns(bunStyle)
        return self

    def addPatty(self, pattyStyle):
        self.burger.setPatty(pattyStyle)
        return self

    def addCheese(self, cheeseStyle):
        self.burger.setCheese(cheeseStyle)
        return self

    def build(self):
        return self.burger

# Now we can build burger based on our requirment and add required bun, patty and cheese
burger = BurgerBuilder()\
            .addBuns("sesame")\
            .addPatty("paneer-patty")\
            .addCheese("amul-cheese")\
            .build()

Now user/client can create an object and update the required customization before using the created object. We can create burgers with sesame seeds and local Amul cheese which was not possible in the Factory method. Note, that the above chaining works as the BurgerBuilder class returns reference to self each time we call its method.


Pros and Cons

Advantages of the Builder pattern include:

  • The user/client can modify the internal representation of the object.

  • Encapsulates code for construction and representation.

  • Provides control over steps of the construction process.

Disadvantages of the Builder pattern include:

  • A distinct ConcreteBuilder must be created for each type of product.

  • Builder classes must be mutable.

  • May hamper/complicate dependency injection.

Comments


bottom of page