Factory Method
Let subclasses decide which class to create, so the code that uses the product never names a concrete type.
Big idea
Factory Method puts object creation behind an overridable method. The base class writes the workflow — "create an enemy, place it, start its AI" — and calls create_enemy() for the one step that varies. Subclasses override that one method to decide which enemy, and the workflow never mentions a concrete class.
The problem it solves
A game's Level.spawn_wave() was written for the forest level:
enemy = Wolf()
enemy.place(x, y)
enemy.start_ai()
Now there's a desert level with scorpions and an ice level with yetis. Copying spawn_wave three times duplicates the placement and AI logic; adding if self.theme == "desert" puts every theme's knowledge into one method that changes every time a level is added.
Think of it like
A franchise bakery chain. Head office writes the opening routine for every shop: unlock, switch on ovens, bake the signature loaf, open the doors. Each branch decides what its signature loaf is — sourdough in one city, rye in another. Head office never changes its routine when a new branch opens; it just calls "bake the signature loaf".
Structure
- Product (
Enemy) — the interface every created object shares. - Concrete products (
Wolf,Scorpion). - Creator (
Level) — holds the workflow and declares the factory method. - Concrete creators (
ForestLevel,DesertLevel) — override the factory method.
In code
class Wolf:
def attack(self): return "bites"
class Scorpion:
def attack(self): return "stings"
class Yeti:
def attack(self): return "throws ice"
class Level:
name = "level"
def create_enemy(self): # the factory method
raise NotImplementedError
def spawn_wave(self, n): # shared workflow, never names a class
enemies = [self.create_enemy() for _ in range(n)]
kinds = type(enemies[0]).__name__
return f"{self.name}: {n} x {kinds}, each {enemies[0].attack()}"
class ForestLevel(Level):
name = "forest"
def create_enemy(self): return Wolf()
class DesertLevel(Level):
name = "desert"
def create_enemy(self): return Scorpion()
class IceLevel(Level): # new level: one small class, no edits elsewhere
name = "ice"
def create_enemy(self): return Yeti()
for level in (ForestLevel(), DesertLevel(), IceLevel()):
print(level.spawn_wave(3))output
forest: 3 x Wolf, each bites
desert: 3 x Scorpion, each stings
ice: 3 x Yeti, each throws iceRun and edit it in the app.
Watch it
How to implement it
- Give all products a common interface.
- In the creator, replace every
ConcreteThing()call in the workflow withself.create_thing(). - Declare
create_thing()in the creator — abstract, or with a sensible default. - Add one concrete creator per variant that overrides it.
In Python, a creator can also take the product class (or any callable) as a constructor argument — Level(enemy_factory=Wolf) — the same idea without subclassing. That's often simpler; the subclass form shines when the creator has other things to override too.
In Factory Method, what do subclasses override?
When to use it — and when not to
Use it when a class can't know ahead of time which objects it must create, when you want subclasses or plug-ins to supply their own products, or when a framework must create objects of user-defined types.
Skip it when there's one product type — Wolf() directly is fine — or when a plain dictionary from names to classes does the job without a class hierarchy.
Pros and cons
| Pros | Cons |
|---|---|
| Workflow code never names concrete classes | A creator subclass per product can bloat the hierarchy |
| New products without editing the workflow (Open/Closed) | Indirection: "where does this object come from?" |
| Creation logic in one well-named place | Overkill for a single product |
How it relates
- It's Template Method applied to creation: the creation step is the template's hook.
- Abstract Factory groups several factory methods to create a matching family.
- Prototype avoids the creator subclass by cloning a sample instead.
- The refactoring Replace Constructor with Factory Method (Simplifying Method Calls) is the first step towards it.
A function make_enemy(kind) returns Wolf() or Scorpion() based on a string. Is that the Factory Method pattern?
Key terms
- Factory method — An overridable method that creates and returns a product object.
- Creator — The class whose workflow calls the factory method.
- Product — The interface shared by every object the factory method can return.
- Simple factory — A plain function or class that picks a product, without subclass overriding.