Published on

[Creational] Factory Method

The Factory Method is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of objects that will be created. Instead of calling a constructor directly, the pattern delegates object creation to a factory method.

Key Concepts

  • Defines an interface for creating an object.
  • Subclasses decide which class to instantiate.
  • Promotes loose coupling by abstracting the instantiation process.

Python Example

Without Factory Method

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

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

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

shelter = AnimalShelter()
animal = shelter.get_animal("dog")
print(animal.speak())  # Output: Woof!

Problem:

  • The AnimalShelter class is tightly coupled to Dog and Cat.
  • Adding a new animal requires modifying get_animal().

With Factory Method

from abc import ABC, abstractmethod

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

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

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

# Factory Method Creator (abstract)
class AnimalShelter(ABC):
    @abstractmethod
    def create_animal(self):
        pass

# Concrete Factories
class DogShelter(AnimalShelter):
    def create_animal(self):
        return Dog()

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

# Client code
shelter = DogShelter()
animal = shelter.create_animal()
print(animal.speak())  # Output: Woof!

Benefits of Factory Method

Encapsulation: Object creation logic is hidden. ✅ Open-Closed Principle: Adding a new animal (e.g., Bird) requires only creating a new subclass. ✅ Loose Coupling: The client doesn't need to know which concrete class is used.