Simple Factory Pattern

by: George El., April 2019, Reading time: 2 minutes

In this post I will continue from my post Abstract Classes in Python and do some modifications in order to make my design more efficient and extensible. First of all I will create a folder named carclasses and create an __init__.py file that will contain the following:

from .vwcar import VWCar
from .car import Car
from .toyotacar import ToyotaCar
from .nullcar import NullCar

This makes this folder a package. Next I will split each class on its own file and move the files inside the carclasses folder

Then I will create another file called carfactory that will contain the CarFactory class. The CarFactory class uses some introspection methods to get all the classes from the cars package. Then creates a dictionary called cars and adds in this dictionary the name and the class of each car. A create_instance method takes as an argument the name of the car and if it matches the classname, it calls the class and creates an object.

from inspect import getmembers, isclass, isabstract
import carclasses

class CarFactory(object):
    cars = {}

    def __init__(self):
        self.load_cars()

    def load_cars(self):
        classes = getmembers(
            carclasses, lambda x: isclass(x) and not isabstract(x))
        # returns the members of a class or module as a tuple
        for name, _class in classes:
            # if it is a class and subclass of Car add it to dictionary
            if isclass(_class) and issubclass(_class, carclasses.Car):
                self.cars.update({name: _class})
        print(self.cars)

    def create_instance(self, carmodel):
        if carmodel in self.cars:
            return self.cars[carmodel]()
        else:
            return carclasses.NullCar(carmodel)

Finally my main file will be like this:

from carfactory import CarFactory

factory = CarFactory()

for carmodel in ["VWCar","ToyotaCar","LadaCar"]:
    car = factory.create_instance(carmodel)
    car.start()
    car.stop()

This approach has a lot of benefits which adhere to the SOLID principles of OOP. First of all I can create new car objects without modifying my code.

comments powered by Disqus