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.
### 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!