Design Pattern in Action(1)
A series of programming design patterns illustration with examples with JavaScript/Python
Creational Pattern — Factory
Simply put, the factory pattern wraps creation (normally through class constructor) of different types of objects with a simple API instead of multiple if..else
statement.
This comes in handy when you want to group several Classes under one API interface for abstraction. It demonstrates in Dynamic programming where the type of objects is decided at runtime.
But be careful with overuse it, as a lot of use cases can be solved simply using Dependency Injection.
See below with an example is in Python. Note the use of ABCMeta Classe to define an agreed interface among child classes.
from abc import ABCMeta, abstractmethod
class IBread(metaclass=ABCMeta):
@staticmethod
@abstractmethod
def make_bread():
pass
class Sourdough(IBread):
def __init__(self, quantity):
self.name = "Sourdough"
self.quantity = quantity
def make_bread(self):
return 'Making {0} of {1}!'.format(self.quantity, self.name)
class Ciabatta(IBread):
def __init__(self, quantity):
self.name = "Ciabatta"
self.quantity = quantity
def make_bread(self):
return 'Making {0} of {1}!'.format(self.quantity, self.name)
class BreadFactory:
@ staticmethod
def produce_bread(bread_type, quantity):
if bread_type == 'Ciabatta':
return Ciabatta(quantity)
if bread_type == 'Sourdough':
return Sourdough(quantity)
return None
sourdough = BreadFactory().produce_bread('Sourdough', 5)
sourdough.make_bread()#Making 5 of Sourdough!
And this is the JavaScript equivalent:
let breadFactoryWarehouse = {};
breadFactoryWarehouse["Ciabatta"] = class Ciabatta {
constructor(quantity) {
this.quantity = quantity;
}
makeBread() {
return `Making ${this.quantity} of Ciabatta!`;
}
};
breadFactoryWarehouse["Sourdough"] = class Sourdough {
constructor(quantity) {
this.quantity = quantity;
}
makeBread() {
return `Making ${this.quantity} of Sourdough!`;
}
};
class BreadFactory {
constructor(type, quantity) {
return new breadFactoryWarehouse[type](quantity);
}
}
const sourdough = new BreadFactory("Sourdough", 5);
sourdough.makeBread;#Making 5 of Sourdough!
Note that we are not using a if..else
statement in the JavaScript implementation. This is a refactor for “open for extension” principle, just in case in the future more bread types will be added, we don’t need to go modify the BreadFactory
itself, but just register the new bread type with breadFactoryWarehouse.
That’s pretty much of it!
Happy Reading!