Bird
Raised Fist0
LLDsystem_design~7 mins

Factory Method pattern in LLD - System Design Guide

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of the Factory Method pattern in system design?
easy
A. To enforce a single instance of a class throughout the application
B. To create objects directly without any abstraction
C. To define an interface for creating objects but let subclasses decide which class to instantiate
D. To provide a global point of access to a resource

Solution

  1. Step 1: Understand the Factory Method pattern goal

    The Factory Method pattern aims to separate object creation from usage by defining an interface for creating objects.
  2. Step 2: Identify the role of subclasses

    Subclasses decide which specific class to instantiate, allowing flexibility and easy extension.
  3. Final Answer:

    To define an interface for creating objects but let subclasses decide which class to instantiate -> Option C
  4. Quick Check:

    Factory Method = Interface for object creation + subclass decides [OK]
Hint: Factory Method lets subclasses choose object types [OK]
Common Mistakes:
  • Confusing Factory Method with Singleton pattern
  • Thinking Factory Method creates objects directly without abstraction
  • Mixing Factory Method with global access patterns
2. Which of the following is the correct way to declare a Factory Method in an interface in a typical object-oriented design?
easy
A. public Product createProduct();
B. public static Product createProduct();
C. public void createProduct();
D. private Product createProduct();

Solution

  1. Step 1: Understand Factory Method signature

    The Factory Method returns an object of a product type, so it must have a return type matching the product interface or class.
  2. Step 2: Check access and static modifiers

    Factory Methods are usually instance methods (not static) and public to allow subclass overriding and usage.
  3. Final Answer:

    public Product createProduct(); -> Option A
  4. Quick Check:

    Factory Method returns product instance, public and non-static [OK]
Hint: Factory Method returns product, not void or static [OK]
Common Mistakes:
  • Using void return type instead of product
  • Making Factory Method static which breaks subclass override
  • Declaring Factory Method private so subclasses can't override
3. Given the following code snippet, what will be the output?
abstract class Creator {
  abstract Product factoryMethod();
  void someOperation() {
    Product product = factoryMethod();
    print(product.operation());
  }
}

class ConcreteProductA implements Product {
  String operation() => "Product A operation";
}

class ConcreteCreatorA extends Creator {
  Product factoryMethod() => ConcreteProductA();
}

void main() {
  Creator creator = ConcreteCreatorA();
  creator.someOperation();
}
medium
A. Product operation
B. No output
C. Error: factoryMethod not implemented
D. Product A operation

Solution

  1. Step 1: Trace the factoryMethod call in ConcreteCreatorA

    ConcreteCreatorA overrides factoryMethod to return ConcreteProductA instance.
  2. Step 2: Call operation() on ConcreteProductA instance

    ConcreteProductA's operation() returns "Product A operation" which is printed.
  3. Final Answer:

    Product A operation -> Option D
  4. Quick Check:

    ConcreteCreatorA creates ConcreteProductA, prints its operation [OK]
Hint: Factory Method returns ConcreteProductA, prints its operation [OK]
Common Mistakes:
  • Assuming abstract Creator can be instantiated
  • Forgetting ConcreteCreatorA overrides factoryMethod
  • Expecting generic Product operation output
4. Identify the error in the following Factory Method implementation:
abstract class Creator {
  Product factoryMethod();
}

class ConcreteCreator extends Creator {
  void factoryMethod() {
    print("Creating product");
  }
}
medium
A. ConcreteCreator's factoryMethod has wrong return type
B. Creator class should not be abstract
C. factoryMethod should be static
D. No error, code is correct

Solution

  1. Step 1: Check method signature in abstract Creator

    factoryMethod returns Product type, so subclass must match return type.
  2. Step 2: Check ConcreteCreator's factoryMethod signature

    It returns void, which conflicts with abstract method's Product return type.
  3. Final Answer:

    ConcreteCreator's factoryMethod has wrong return type -> Option A
  4. Quick Check:

    Return type mismatch causes error [OK]
Hint: Return type must match abstract method in subclass [OK]
Common Mistakes:
  • Ignoring return type mismatch
  • Thinking abstract class can't have abstract methods
  • Assuming static needed for Factory Method
5. You are designing a system that supports multiple types of notifications: Email, SMS, and Push. Using the Factory Method pattern, how should you organize your classes to allow easy addition of new notification types without modifying existing code?
hard
A. Create separate unrelated classes for each notification type without a common interface
B. Create an abstract NotificationCreator with a factoryMethod returning Notification; implement subclasses EmailCreator, SMSCreator, PushCreator each creating respective Notification objects
C. Use static methods in Notification class to create different notification types
D. Create a single Notification class with if-else to handle all notification types

Solution

  1. Step 1: Apply Factory Method pattern structure

    Define an abstract creator class with a factoryMethod that returns a Notification interface or abstract class.
  2. Step 2: Implement concrete creators for each notification type

    Each subclass (EmailCreator, SMSCreator, PushCreator) overrides factoryMethod to create its specific Notification object.
  3. Step 3: Ensure easy extension without modifying existing code

    Adding new notification types means adding new creator subclasses without changing existing ones, following open-closed principle.
  4. Final Answer:

    Create an abstract NotificationCreator with a factoryMethod returning Notification; implement subclasses EmailCreator, SMSCreator, PushCreator each creating respective Notification objects -> Option B
  5. Quick Check:

    Factory Method enables easy extension via subclassing [OK]
Hint: Use abstract creator + subclasses for each notification type [OK]
Common Mistakes:
  • Using if-else inside one class, violating open-closed principle
  • Using static methods, reducing flexibility
  • Not using a common interface for notifications
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard