0
0
LLDsystem_design~7 mins

Factory Method pattern in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
When creating objects directly in code, changes to the object types require modifying the code everywhere. This tight coupling makes the system hard to extend or maintain, especially when new object types are added or existing ones change.
Solution
The Factory Method pattern solves this by defining an interface for creating objects but lets subclasses decide which class to instantiate. This way, object creation is delegated to subclasses, reducing direct dependencies and making the system easier to extend without changing existing code.
Architecture
Creator
+ factory()
+ factory()
Product

This diagram shows the Creator class with a factory method that is overridden by ConcreteCreator subclasses to instantiate ConcreteProduct objects, all implementing the Product interface.

Trade-offs
✓ Pros
Decouples object creation from usage, improving code flexibility.
Makes it easy to introduce new product types without changing existing code.
Supports the Open/Closed Principle by allowing extension without modification.
✗ Cons
Increases the number of classes and complexity due to additional creator subclasses.
Can be overkill for simple systems with few object types.
Requires careful design to avoid unnecessary subclass proliferation.
Use when a system needs to create objects from a family of related classes and you want to delegate the instantiation to subclasses to support easy extension and maintenance.
Avoid when the number of product types is fixed and unlikely to change, or when object creation is simple and does not require subclassing.
Real World Examples
Netflix
Netflix uses the Factory Method pattern to create different types of streaming sessions depending on device capabilities, allowing easy addition of new device types without changing core streaming logic.
Uber
Uber applies Factory Method to instantiate different ride request handlers based on ride types (e.g., UberX, UberPool), enabling flexible addition of new ride categories.
Amazon
Amazon uses Factory Method to create various payment processors depending on payment method, facilitating integration of new payment options without modifying order processing code.
Code Example
The before code tightly couples AnimalShelter to specific animal classes, requiring modification to add new animals. The after code uses the Factory Method pattern by defining an abstract create_animal method that subclasses override to instantiate specific animals. This decouples object creation from usage and supports easy extension.
LLD
### Before (without Factory Method) ###
class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class AnimalShelter:
    def adopt(self, animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            raise ValueError("Unknown animal type")

shelter = AnimalShelter()
dog = shelter.adopt("dog")
print(dog.speak())  # Woof!

### After (with Factory Method) ###
from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class AnimalShelter(ABC):
    @abstractmethod
    def create_animal(self):
        pass

    def adopt(self):
        animal = self.create_animal()
        return animal

class DogShelter(AnimalShelter):
    def create_animal(self):
        return Dog()

class CatShelter(AnimalShelter):
    def create_animal(self):
        return Cat()

shelter = DogShelter()
dog = shelter.adopt()
print(dog.speak())  # Woof!

shelter = CatShelter()
cat = shelter.adopt()
print(cat.speak())  # Meow!
OutputSuccess
Alternatives
Abstract Factory
Creates families of related objects without specifying their concrete classes, while Factory Method creates one product per method.
Use when: Use Abstract Factory when you need to create multiple related objects together that must be compatible.
Builder
Separates object construction from its representation, focusing on step-by-step creation, unlike Factory Method which focuses on object instantiation.
Use when: Choose Builder when you need to construct complex objects with many parts or configurations.
Simple Factory (not a GoF pattern)
Uses a single method to create objects without subclassing, unlike Factory Method which uses inheritance.
Use when: Use Simple Factory for simpler scenarios where subclassing is unnecessary.
Summary
Factory Method pattern delegates object creation to subclasses to reduce tight coupling.
It improves system extensibility by allowing new product types without modifying existing code.
This pattern is useful when a system needs flexible and maintainable object instantiation.