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-
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
PythonOutput:
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
PlaintextExamples
We are discussing the Factory pattern examples by implementing a factory for different transports. Two implementations are shown in the follwing example-
- Simple Factory Implementation – Example #1
- Factory Method Implementation – Example #2
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
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"""
...
PythonBike Class [Item Class]
class Bike:
def start(self) -> None:
print("Bike started")
def stop(self) -> None:
print("Bike stopped")
def repair(self) -> None:
print("Bike repair")
PythonCar Class [Item Class]
class Car:
def start(self) -> None:
print("Car started")
def stop(self) -> None:
print("Car stopped")
def repair(self) -> None:
print("Car repair")
PythonPlane Class [Item Class]
class Plane:
def start(self) -> None:
print("Plane started")
def stop(self) -> None:
print("Plane stopped")
def repair(self) -> None:
print("Plane repair")
PythonTransport Factory Class
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
PythonDemo
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()
PythonOutput
Bike started
Bike stopped
Car started
Plane started
Plane stopped
Plane repair
PlaintextExample #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
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
PythonBus Class [Road Transport – Concrete Item Class]
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")
PythonBike Class [Road Transport – Concrete Item Class]
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")
PythonCar Class [Road Transport – Concrete Item 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")
PythonPlane Class [Air Transport – Concrete Item 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")
PythonHelicopter Class [Air Transport – Concrete Item 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")
PythonTransport Factory [Abstract Class]
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
PythonRoad Transport Factory
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
PythonAir Transport Factory
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
PythonDemo
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()
PythonOutput:
Output will be as below.
Bus started
Bus stopped
Helicopter started
Helicopter stopped
Bike repair
PlaintextSource Code
Use the following link to get the source code:
Example | Python Implementation Source Code Link |
---|---|
Example #1: Transport | GitHub |
Example #2: Transport [Factory Method] | GitHub |
Other Code Implementations
Use the following links to check Factory pattern implementation in other programming languages.