What It Is
The Factory Method pattern puts the creation of an object behind a function. The caller says what it wants — the factory decides which concrete class to build and returns it.
The caller never touches the concrete classes, so new kinds can be added without changing any calling code. In Python this is simply a new_something() function whose return type is a protocol.
Example: A Storage Factory
new_storage("disk") and new_storage("memory") return different concrete classes behind the same Storage protocol — the caller cannot tell the difference, and does not need to.
The factory picks the class
The match over kinds lives in one place — the factory. The rest of the program only knows the protocol.
Output: complete Python program
from typing import Protocol
class Storage(Protocol):
def save(self, data: str) -> str: ...
class DiskStore:
def save(self, data: str) -> str:
return "disk: saved " + data
class MemoryStore:
def save(self, data: str) -> str:
return "memory: kept " + data
# The factory decides which concrete class to build.
def new_storage(kind: str) -> Storage:
match kind:
case "memory":
return MemoryStore()
case _:
return DiskStore()
for kind in ["disk", "memory"]:
s = new_storage(kind)
print(s.save("order #1042"))
When to Use It
Use it when the concrete class depends on something known only at run time — a config value, a user choice, an environment — or when you want creation logic in exactly one place.
Skip it when there is only one implementation and no sign of a second. store = DiskStore() needs no factory.
Pros and Cons
Pros: creation logic in one place; callers depend only on the protocol; adding a kind touches only the factory.
Cons: one more layer to read through; with a single implementation it is pure ceremony.