How do you implement a system design pattern like the Singleton or Factory pattern?
Design patterns offer reusable solutions to common software design problems. The Singleton and Factory patterns are fundamental creational patterns, each addressing object instantiation with distinct goals and use cases in system design.
Singleton Pattern
The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. It's commonly used for managing resources like database connection pools, loggers, or configuration settings where a single, consistent instance across the application is critical to prevent resource contention or ensure unified behavior.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Usage:
s1 = Singleton()
s2 = Singleton()
# print(s1 is s2) # Output: True, confirming single instance
Factory Pattern
The Factory pattern provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. This pattern is useful when object creation logic is complex, depends on dynamic conditions, or when you want to decouple the client code from the concrete classes being instantiated, promoting flexibility and extensibility.
class ProductA:
def operation(self):
return "Product A operation"
class ProductB:
def operation(self):
return "Product B operation"
class ProductFactory:
def create_product(self, type):
if type == "A":
return ProductA()
elif type == "B":
return ProductB()
else:
raise ValueError("Invalid product type")
# Usage:
factory = ProductFactory()
product1 = factory.create_product("A")
product2 = factory.create_product("B")
# print(product1.operation()) # Output: Product A operation
Key Differences and When to Use
- Singleton: Focuses on ensuring a class has *only one instance* globally and providing a simple access point.
- Factory: Focuses on abstracting the object creation process, allowing *families of related objects* to be created without exposing their concrete classes to the client.
- Use Singleton when you require a strictly unique instance of a resource or configuration throughout your application's lifecycle.
- Use Factory when you need to delegate object instantiation based on runtime parameters, configuration, or when different subclasses might produce different types of objects.