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