Abstract Factory Pattern

Sean Bradley
Design Patterns In Python
4 min readApr 9, 2019

--

The Abstract Factory Pattern adds an abstraction layer over multiple other creational pattern implementations.

To begin with, in simple terms, think if it as a Factory that can return Factories. Although you will find examples of it also begin used to return Builder, ProtoTypes, Singletons or other design pattern implementations.

Terminology

  • Client: The client application that calls the Abstract Factory. It’s the same process as the Concrete Creator in the Factory design pattern.
  • Abstract Factory: A common interface over all of the sub factories.
  • Concrete Factory: The sub factory of the Abstract Factory and contains method(s) to allow creating the Concrete Product.
  • Abstract Product: The interface for the product that the sub factory returns.
  • Concrete Product: The object that is finally returned.

Abstract Factory UML Diagram

Source Code

./abstract_factory/abstract_factory_concept.py

"""
Abstract Factory Concept Sample Code
https://sbcode.net/python/abstract_factory/#abstract_factoryabstract_factory_conceptpy
"""
from abc import ABCMeta, abstractmethod
from factory_a import FactoryA
from factory_b import FactoryB
class IAbstractFactory(metaclass=ABCMeta):
"Abstract Factory Interface"
@staticmethod
@abstractmethod
def create_object(factory):
"The static Abstract factory interface method"
class AbstractFactory(IAbstractFactory):
"The Abstract Factory Concrete Class"
@staticmethod
def create_object(factory):
"Static get_factory method"
try:
if factory in ['aa', 'ab', 'ac']:
return FactoryA().create_object(factory[1])
if factory in ['ba', 'bb', 'bc']:
return FactoryB().create_object(factory[1])
raise Exception('No Factory Found')
except Exception as _e:
print(_e)
return None
# The Client
PRODUCT = AbstractFactory.create_object('ab')
print(f"{PRODUCT.__class__}")
PRODUCT = AbstractFactory.create_object('bc')
print(f"{PRODUCT.__class__}")

./abstract_factory/factory_a.py

"""
FactoryA Sample Code
https://sbcode.net/python/abstract_factory/#abstract_factoryfactory_apy
"""
from abc import ABCMeta, abstractmethodclass IProduct(metaclass=ABCMeta):
"A Hypothetical Class Interface (Product)"
@staticmethod
@abstractmethod
def create_object():
"An abstract interface method"
class ConcreteProductA(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductA"
def create_object(self):
return self
class ConcreteProductB(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductB"
def create_object(self):
return self
class ConcreteProductC(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductC"
def create_object(self):
return self
class FactoryA:
"The FactoryA Class"
@staticmethod
def create_object(some_property):
"A static method to get a concrete product"
try:
if some_property == 'a':
return ConcreteProductA()
if some_property == 'b':
return ConcreteProductB()
if some_property == 'c':
return ConcreteProductC()
raise Exception('Class Not Found')
except Exception as _e:
print(_e)
return None

./abstract_factory/factory_b.py

"""
FactoryB Sample Code
https://sbcode.net/python/abstract_factory/#abstract_factoryfactory_bpy
"""
from abc import ABCMeta, abstractmethodclass IProduct(metaclass=ABCMeta):
"A Hypothetical Class Interface (Product)"
@staticmethod
@abstractmethod
def create_object():
"An abstract interface method"
class ConcreteProductA(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductA"
def create_object(self):
return self
class ConcreteProductB(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductB"
def create_object(self):
return self
class ConcreteProductC(IProduct):
"A Concrete Class that implements the IProduct interface"
def __init__(self):
self.name = "ConcreteProductC"
def create_object(self):
return self
class FactoryB:
"The FactoryB Class"
@staticmethod
def create_object(some_property):
"A static method to get a concrete product"
try:
if some_property == 'a':
return ConcreteProductA()
if some_property == 'b':
return ConcreteProductB()
if some_property == 'c':
return ConcreteProductC()
raise Exception('Class Not Found')
except Exception as _e:
print(_e)
return None

Output

python ./abstract_factory/abstract_factory_concept.py
<class 'factory_a.ConcreteProductB'>
<class 'factory_b.ConcreteProductC'>

Abstract Factory Overview Video

Abstract Factory Example Use Case

Visit Abstract Factory — Design Patterns In Python (sbcode.net) for an example use case of the Abstract Factory pattern.

An example use case may be that you have a furniture shop front. You sell many different kinds of furniture. You sell chairs and tables. And they are manufactured at different factories using different unrelated processes that are not important for your concern. You only need the factory to deliver.

You can create an extra module called FurnitureFactory , to handle the chair and table factories, thus removing the implementation details from the client.

In the image below, there are several factories, all accessed via the abstract factory of the selection panel.

Video of an Abstract Factory Pattern use case

Summary

  • Use when you want to provide a library of relatively similar products from multiple different factories.
  • You want the system to be independent of how the products are created.
  • It fulfills all of the same use cases as the Factory method, but is a factory for creational pattern type methods.
  • The client implements the abstract factory interface, rather than all the internal logic and Factories. This allows the possibility of creating a library that can be imported for using the Abstract Factory.
  • The Abstract Factory defers the creation of the final products/objects to its concrete factory subclasses.
  • You want to enforce consistent interfaces across products.
  • You want the possibility to exchange product families.

Thankyou for reading my quick tutorial on the Abstract Factory Design Pattern. For more design patterns please visit my series on Design Patterns in Python at https://medium.com/design-patterns-in-python

Sean

Design Patterns In Python (Book)

You can also buy this series in paperback.
Book provides FREE access to online instructional videos.
Design Patterns In Python : ASIN B08XLJ8Z2J

--

--

Sean Bradley
Design Patterns In Python

Developer of real time, low latency, high availability, asynchronous, multi threaded, remotely managed, fully automated and monitored solutions.