Understanding the Object Factory Design Pattern with Python Examples
Object Factory is a design pattern that centralizes object creation, enhancing decoupling, extensibility, and management of instances, and this article explains its principles, benefits, and provides five Python code examples illustrating various scenarios such as type-based creation, configuration-driven instantiation, logging factories, singleton factories, and object caching.
Object Factory (Object Factory) is a design pattern used to create and manage the instantiation process of objects. It offers a flexible way to create objects, making code more extensible and maintainable.
In the Object Factory pattern, a factory class is responsible for instantiating objects and returning appropriate object instances to the caller, so the caller does not need to depend directly on concrete object classes.
Benefits of using the Object Factory pattern include:
Decoupling : Callers obtain objects through the factory, reducing code coupling.
Extensibility : Adding new product classes only requires updating the factory, not the caller code.
Managed instantiation : The factory can handle creation, caching, and reuse of objects.
Complex scenarios such as conditional creation or configuration‑driven creation are also supported.
The article presents five illustrative Python examples.
Example 1: Creating different types of product objects
class Product:
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
class ProductFactory:
@staticmethod
def create_product(product_type, name):
if product_type == "A":
return ProductA(name)
elif product_type == "B":
return ProductB(name)
else:
raise ValueError("Invalid product type")
class ProductA(Product):
def __init__(self, name):
super().__init__(name)
class ProductB(Product):
def __init__(self, name):
super().__init__(name)
# Using the object factory to create different product objects
product_factory = ProductFactory()
product_a = product_factory.create_product("A", "Apple")
product_b = product_factory.create_product("B", "Banana")Example 2: Dynamically creating objects based on a configuration file
import json
class Product:
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
class ProductFactory:
def __init__(self, config_file):
self.config = self.load_config(config_file)
@staticmethod
def load_config(config_file):
with open(config_file, 'r') as f:
return json.load(f)
def create_product(self, name):
product_type = self.config.get("product_type", "default")
if product_type == "A":
return ProductA(name)
elif product_type == "B":
return ProductB(name)
else:
return Product(name)
class ProductA(Product):
def __init__(self, name):
super().__init__(name)
class ProductB(Product):
def __init__(self, name):
super().__init__(name)
# Using the object factory to create a product based on configuration
product_factory = ProductFactory("config.json")
product = product_factory.create_product("Apple")Example 3: Factory method pattern for creating different logger objects
import logging
class Logger:
def log(self, message):
pass
class FileLogger(Logger):
def log(self, message):
# Implement file‑writing logic
pass
class DatabaseLogger(Logger):
def log(self, message):
# Implement database‑writing logic
pass
class LoggerFactory:
@staticmethod
def create_logger(logger_type):
if logger_type == "file":
return FileLogger()
elif logger_type == "database":
return DatabaseLogger()
else:
raise ValueError("Invalid logger type")
# Using the factory method to create a logger
logger_factory = LoggerFactory()
logger = logger_factory.create_logger("file")
logger.log("Log message")Example 4: Factory for creating a singleton object
class Singleton:
def __init__(self):
pass
class SingletonFactory:
instance = None
@classmethod
def get_instance(cls):
if cls.instance is None:
cls.instance = Singleton()
return cls.instance
# Getting the singleton instance via the factory
singleton = SingletonFactory.get_instance()Example 5: Factory that caches created objects
class Product:
def __init__(self, name):
self.name = name
class ProductFactory:
_product_cache = {}
@staticmethod
def create_product(name):
if name in ProductFactory._product_cache:
return ProductFactory._product_cache[name]
else:
product = Product(name)
ProductFactory._product_cache[name] = product
return product
# Using the factory with caching
product_factory = ProductFactory()
product_a = product_factory.create_product("A")
product_b = product_factory.create_product("B")
product_a_cached = product_factory.create_product("A") # Retrieved from cacheThese examples demonstrate how the Object Factory pattern can be applied in various contexts, from simple type‑based creation to configuration‑driven instantiation, logger factories, singleton factories, and object caching, allowing developers to design flexible and maintainable object creation mechanisms.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.