Factory and Abstract Factory
coreintermediateA Factory is a function that picks which class to instantiate based on input, so callers never write ClassName(...) directly. An Abstract Factory is a family of factories that each produce a matching set of related objects.
Think of it as
Without a factory, the caller writes if channel == "email": EmailNotifier() else: SmsNotifier() itself — that branching gets copy-pasted everywhere a notifier is created. A factory function centralizes that decision once; callers just ask notifier_factory("email") and get the right object back. An Abstract Factory extends the same idea to a whole family: instead of one object, DarkThemeFactory produces a DarkButton AND a DarkCheckbox that are guaranteed to match, so a caller building a toolbar never accidentally mixes a dark button with a light checkbox.
What we're doing: Build a Factory that picks a notification channel, then an Abstract Factory that produces a matching family of themed UI widgets.
- 10
- notifier_factory is a plain function — the whole Factory pattern is this if/return branching in one place.
- 34
- WidgetFactory declares one creation method per product in the family (button, checkbox).
- 35
- DarkThemeFactory implements both methods so every widget it returns matches the same theme.
Email: your order shipped
[dark button] [dark checkbox]Why this works: render_toolbar never names DarkButton or DarkCheckbox — it only calls factory.create_button()/create_checkbox(), so swapping in a LightThemeFactory later changes nothing about render_toolbar itself. That is the payoff: new variants are new classes, not new branches scattered through calling code.
Reaching for Abstract Factory when a plain Factory already solves it
Wrong
Better
What you see: Not a runtime error — a design smell: a class hierarchy with exactly one method and one implementation per branch, doing what an if/return already did in a third of the code.
Why: Abstract Factory earns its complexity when there is a FAMILY of related products that must stay consistent (a button that matches a checkbox). With a single product type, it just adds classes without adding any guarantee a function did not already provide.
- notifier_factory("email") — caller states intent, not a class name
- picks EmailNotifier — the factory owns the if/elif branching
- notifier.send(msg) — caller only ever sees the shared interface
Factory vs. Abstract Factory
Together
Remember: Factory centralizes "which class do I instantiate?" behind one function; Abstract Factory centralizes it for a whole family of related objects that must stay consistent with each other.
See also: strategy · builder · classes and objects

