Factories centralize object creation behind a function or class method so callers stay decoupled from concrete types. Builders assemble complex objects step-by-step when constructors would need too many parameters or optional combinations.
Often no. dataclass with defaults, model_validate, or a single factory function covers many cases. Builders help when assembly is multi-step and order matters.
Where should factories live?
In the module that owns the product types, or a dedicated factories.py when creation crosses subpackages.
How do factories help testing?
Pass a factory callable that returns fakes/mocks. Production uses real factory; tests inject lambda: FakeStorage().
Are classmethods factories?
Yes. from_dict, from_url, and parse are standard Python factory methods.
Can builders be dataclasses?
Use a mutable builder class or dataclass with frozen=False internally; freeze the product with frozen=True.
What about __init_subclass__ for registration?
Plugin frameworks register subclasses automatically - a form of factory discovery.
How does Pydantic fit?
Model.model_validate(data) is a validated factory from dicts/JSON - prefer it for config objects.
Should build() return a copy?
If the product is mutable, returning a deep copy prevents callers from mutating cached builder state.
Factory vs dependency injection container?
DI containers call factories/providers. Simple apps use plain functions without a framework.
How do I type a factory?
Callable[[], Storage] or Protocol with a create() method. Generics when product type varies.