Design Pattern: Factory Pattern in Python

Factory design pattern is used, so that a client(the client code) can provide some criteria and and ask for an object. And the factory will generate the object based on the provided criteria and return that.

The client is completely unaware of how the object is generated. The factory hides the object creation process and takes the full responsibility of the object creation process. That way the factory pattern works as a object factory.

This way we are able to decouple the object creation and object usage, from each other.

NOTES

In this article, we discuss the implementation of the Factory Pattern in Python.

See the Factory in other languages in the “Other Code Implementations” section. Or, use the link below to check the details of the Factory Pattern-

Implementation

Let’s consider a general implementation of Factory pattern in Python. We have some classes for items and we are implementing factory for those item object creation-

Create an abstract class (or a Protocol).
Create item classes and inherit the abstract class (or implement the protocol).
Create a factory class, and in a method accept a param(identifier for the type of object). Based on the provided identifier create object and return that.

Here is a simple example of Factory pattern implementation in Python-

from abc import ABC, abstractmethod


# Step 1: Define the BaseItem interface (abstract class in Python)
class BaseItem(ABC):
    @abstractmethod
    def operation1(self) -> None:
        pass

    @abstractmethod
    def operation2(self) -> None:
        pass


# Step 2: Define concrete classes for Item1 and Item2
class Item1(BaseItem):
    def operation1(self) -> None:
        print("Item 1: operation 1")

    def operation2(self) -> None:
        print("Item 1: operation 2")


class Item2(BaseItem):
    def operation1(self) -> None:
        print("Item 2: operation 1")

    def operation2(self) -> None:
        print("Item 2: operation 2")


# Step 3: Define the Factory class
class Factory:
    @staticmethod
    def get_item(item_type: int) -> BaseItem:
        if item_type == 1:
            return Item1()
        elif item_type == 2:
            return Item2()
        else:
            return None


# Step 4: Demo
if __name__ == "__main__":
    # Get Item1 and call its operations
    item1 = Factory.get_item(1)
    item1.operation1()  # Output: Item 1: operation 1
    item1.operation2()  # Output: Item 1: operation 2

    # Get Item2 and call its operations
    item2 = Factory.get_item(2)
    item2.operation1()  # Output: Item 2: operation 1
    item2.operation2()  # Output: Item 2: operation 2
Python

Output:

Output of the above code will be as below-

Item 1: operation 1
Item 1: operation 2
Item 2: operation 1
Item 2: operation 2
Plaintext

Examples

We are discussing the Factory pattern examples by implementing a factory for different transports. Two implementations are shown in the follwing example-

Example #1: Transport

Let’s implement Factory patern for creating transport objects.

We have classes for representing bike, car, plane, etc. We want to generate object of these classes using a factory.

Transport Protocol

Define “Transport” protocol.
Declare methods that will be required by transpots. Here we have defined methods – “start“, “stop“, “repair“.
from typing import Protocol, Optional


class Transport(Protocol):
    def start(self) -> None:
        """Start transport"""
        ...

    def stop(self) -> None:
        """Stop transport"""
        ...

    def repair(self) -> None:
        """Repair transport"""
        ...
Python

Bike Class [Item Class]

Create “Bike” class.
Define method “start“, “stop“, “repair” for implementing the “Transport” protocol.
class Bike:
    def start(self) -> None:
        print("Bike started")

    def stop(self) -> None:
        print("Bike stopped")

    def repair(self) -> None:
        print("Bike repair")
Python

Car Class [Item Class]

Create “Car” class.
Define method “start“, “stop“, “repair” for implementing the “Transport” protocol.
class Car:
    def start(self) -> None:
        print("Car started")

    def stop(self) -> None:
        print("Car stopped")

    def repair(self) -> None:
        print("Car repair")
Python

Plane Class [Item Class]

Create “Plane” class.
Define method required for the “Transport” protocol implementation.
class Plane:
    def start(self) -> None:
        print("Plane started")

    def stop(self) -> None:
        print("Plane stopped")

    def repair(self) -> None:
        print("Plane repair")
Python

Transport Factory Class

Define class “TransportFactory“.
Define static method “get_transport“.
Accept param “transport_type” in the method “get_transport”.
In the method implementation create object based on the param value “transport_type“, and return the object.
class TransportFactory:
    @staticmethod
    def get_transport(transport_type: str) -> Optional[Transport]:
        transport_type = transport_type.lower()
        if transport_type == "bike":
            return Bike()
        
        if transport_type == "car":
            return Car()
        
        if transport_type == "plane":
            return Plane()
        
        return None
Python

Demo

Here is the demo code where we are using the “TransportFactory“, and passing transport type as identifier string. And getting the relevent object back.

# Demo usage
def main() -> None:
    transport_factory = TransportFactory()

    # Get Bike and start it
    transport1 = transport_factory.get_transport("bike")
    if transport1:
        transport1.start()
        transport1.stop()

    # Get Car and start it
    transport2 = transport_factory.get_transport("car")
    if transport2:
        transport2.start()

    # Get Plane and start it
    transport3 = transport_factory.get_transport("plane")
    if transport3:
        transport3.start()
        transport3.stop()
        transport3.repair()


if __name__ == "__main__":
    main()
Python

Output

Bike started
Bike stopped

Car started

Plane started
Plane stopped
Plane repair
Plaintext

Example #2: Transport [Factory Method]

Let’s try the Factory method for generating transport objects.

Here we are using abstract class, but you can use protocol if you prefer.

Transport Abstract Class

Create abstract class “Transport” by inheriting from “abc”.
Declare abstract methods – “start“, “stop“, “repair“.
from abc import ABC, abstractmethod


class Transport(ABC):
    @abstractmethod
    def start(self) -> None:
        pass

    @abstractmethod
    def stop(self) -> None:
        pass

    @abstractmethod
    def repair(self) -> None:
        pass
Python

Bus Class [Road Transport – Concrete Item Class]

Define class “Bus“.
Inherit from “Transport” abstract class.
Define methods “start“, “stop“, “repair“.
from transport import Transport

class Bus(Transport):
    def start(self) -> None:
        print("Bus started")

    def stop(self) -> None:
        print("Bus stopped")

    def repair(self) -> None:
        print("Bus repair")
Python

Bike Class [Road Transport – Concrete Item Class]

Define class “Bike“.
Inherit from “Transport” abstract class.
Define methods “start“, “stop“, “repair“.
from transport import Transport

class Bike(Transport):
    def start(self) -> None:
        print("Bike started")

    def stop(self) -> None:
        print("Bike stopped")

    def repair(self) -> None:
        print("Bike repair")
Python

Car Class [Road Transport – Concrete Item Class]

Define class “Car“.
Inherit from “Transport” abstract class.
from transport import Transport

class Car(Transport):
    def start(self) -> None:
        print("Car started")

    def stop(self) -> None:
        print("Car stopped")

    def repair(self) -> None:
        print("Car repair")
Python

Plane Class [Air Transport – Concrete Item Class]

Define class “Plane“.
Inherit from “Transport” abstract class.
from transport import Transport

class Plane(Transport):
    def start(self) -> None:
        print("Plane started")

    def stop(self) -> None:
        print("Plane stopped")

    def repair(self) -> None:
        print("Plane repair")
Python

Helicopter Class [Air Transport – Concrete Item Class]

Define class “Helicopter“.
Inherit from “Transport” abstract class.
from transport import Transport

class Helicopter(Transport):
    def start(self) -> None:
        print("Helicopter started")

    def stop(self) -> None:
        print("Helicopter stopped")

    def repair(self) -> None:
        print("Helicopter repair")
Python

Transport Factory [Abstract Class]

Define abstract class “TransportFactory
Declare abstract method “get_transport“. This method is reponsible for generating “Transport” objects.
Define other utilility methods(if required).
from abc import ABC, abstractmethod
from transport import Transport


class TransportFactory(ABC):
    def operate_transport(self, name: str) -> None:
        transport = self.get_transport(name)
        if transport:
            transport.start()
            transport.stop()

    def repair_transport(self, name: str) -> None:
        transport = self.get_transport(name)
        if transport:
            transport.repair()

    @abstractmethod
    def get_transport(self, name: str) -> Transport:
        pass
Python

Road Transport Factory

Define class “RoadTransportFactory“.
Inherit from abstract class “TransportFactory“.
Define method “get_transport” and based on the param generated objects only for the road transports.
from transport_factory import TransportFactory
from car import Car
from bike import Bike
from bus import Bus


class RoadTransportFactory(TransportFactory):
    def get_transport(self, name: str) -> Transport:
        if name.lower() == "car":
            return Car()
        elif name.lower() == "bike":
            return Bike()
        elif name.lower() == "bus":
            return Bus()
        return None
Python

Air Transport Factory

Define class “AirTransportFactory“.
Inherit from abstract class “TransportFactory“.
Define method “get_transport” and based on the param generated objects only for the air transports.
from transport_factory import TransportFactory
from plane import Plane
from helicopter import Helicopter


class AirTransportFactory(TransportFactory):
    def get_transport(self, name: str) -> Transport:
        if name.lower() == "plane":
            return Plane()
        
        if name.lower() == "helicopter":
            return Helicopter()
            
        return None
Python

Demo

Now we can use either “RoadTransportFactory” or “AirTransportFactory” according to our need, to generate relevent transport objects.

def main():
    # Create instances of both factories
    road_factory = RoadTransportFactory()
    air_factory = AirTransportFactory()

    # Operate and repair various transports
    road_factory.operate_transport("bus")
    air_factory.operate_transport("helicopter")
    road_factory.repair_transport("bike")


if __name__ == "__main__":
    main()
Python

Output:

Output will be as below.

Bus started
Bus stopped
Helicopter started
Helicopter stopped
Bike repair
Plaintext

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Factory pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.