Factory In Python

11 Jul 2020

Factory In Python

We will see ways to decouple code namely factory, factory method pattern and abstract factory pattern

Overview

The Factory Method and Abstract Factory patterns was used as an workaround for the lack of first-class functions and classes in less powerful programming languages like cpp and java. That way, It is a poor fit for Python where we can instead simply pass a class or a factory function when a library needs to create objects on our behalf.

# from wikipedia
from abc import ABC, abstractmethod
from sys import platform


class Button(ABC):

    @abstractmethod
    def paint(self):
        pass


class LinuxButton(Button):
    def paint(self):
        return 'Render a button in a Linux style'


class WindowsButton(Button):

    def paint(self):
        return 'Render a button in a Windows style'


class MacOSButton(Button):

    def paint(self):
        return 'Render a button in a MacOS style'


if platform == "linux":
    factory = LinuxButton
elif platform == "darwin":
    factory = MacOSButton
elif platform == "win32":
    factory = WindowsButton
else:
    raise NotImplementedError(
        f'Not implemented for your platform: {platform}'
    )

button = factory()
result = button.paint()
print(result)

Rather we will see these pattern from Maintainability/ Flexibility/ Testibility point of view which will mostly depend on how we decouple components.

Simple Factory

it abstract the creation details of the product from our caller.

Let's understand it with help of an problem. Suppose you represent Ford from “Ford vs Ferrari” and want to write a class which will represent Cars for some races

problem_simple_factory1

SO we want to add more kind of cars. Note that the Ford class(creational class) will be creating actual class(Product class(s)) based on type of race passed to it. We will run LMPCar in LeMans race and Formula1 Car in grand prix.

problem_simple_factory2

So if more cars are added/deleted, you need to modify code. Suppose we want to close classes for modification. What should we do?

Extra thought: Closed for modification?? why ??? suppose it is a library which takes any type of car and library do certain operation on it.

Introducing Simple factory

simple_factory

By encapsulating the car creation in one class, we now have only one place to make modifications when the implementation changes.

Factory Method Pattern

it provides an interface for creating objects but allows subclasses to provide implementation of the type of an object that will be created.

To understand above statement, we go ahead with our previous ford example. Now Ford have become famous in car racing. Everybody wants to partner with Ford like Lotus and Cooper. As a good car producer, you want to ensure the quality of the car and you want them to use your time tested code. But even then allow them to create their own car.

Introducing Factory Method Pattern

factory_with_simple

To checkout difference, consider User hierarchy, Creational class(s) and Product class(s). Factory method design pattern is one that provides an interface for creating objects but allows subclasses to alter the type of an object that will be created.

Abstract Factory Pattern

it encapsulate all simple factories that have common theme without specifying their name.

Suppose we want to put a little control on how factories can work

abstract_factory_pattern

What’s next

License

MIT