Factory Method¶
Intent¶
Delegate object creation to subclasses/modules so callers depend on a stable product interface rather than concrete types.
Use When¶
- A base workflow needs a
Productinterface, but the concrete product varies by environment, feature flag, or subtype. - You want to keep callers stable while adding new product implementations over time.
- Construction logic must stay testable (swap a fake product in tests).
Prefer Something Else When¶
- There’s only one concrete type and no realistic plan for variants (a plain constructor or function is simpler).
- Selection is pure configuration and can live in a composition root (DI/container may be enough).
Minimal Structure¶
Product(interface/abstract type)Creator(base type withfactoryMethod(): Product)ConcreteCreatorXoverridesfactoryMethodto returnConcreteProductXCreator.operation()callsfactoryMethodand works only withProduct
Implementation Steps¶
- Extract a
Productinterface from what callers actually need. - Move “new + wiring” into a single
factoryMethod()seam. - Ensure
Creatorcode never mentions concrete products. - Keep selection logic near configuration boundaries (module wiring, DI).
Pitfalls¶
- Factory method becomes a switch: if you keep adding
if/elseinside the factory, consider a registry or Abstract Factory. - Leaky abstractions: callers should not type-check concrete products to get work done.
Testing Checklist¶
- For each concrete creator, assert it returns the expected concrete product (or behavior).
- Unit-test
Creator.operation()with a test creator that returns a fake product. - Add a “new variant” test that demonstrates adding a product does not require changing callers.