Abstract Factory
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
A factory of factories.
The Abstract Factory pattern is a single object that can create a whole family
of related products, all guaranteed to match. Instead of one createButton(), it offers
createButton(), createCheckbox(), createMenu() — all for the same
look-and-feel.
Example: a GUIFactory. A MacFactory makes Mac-style buttons and checkboxes;
a WindowsFactory makes Windows-style ones. Swap the factory and the whole UI theme changes
consistently.
# Problem: UI pieces from mixed families look inconsistent. button = WinButton() checkbox = MacCheckbox() # Windows button + Mac checkbox — wrong button.render(); checkbox.render()
# Fix: Abstract Factory creates a matching family of products. from abc import ABC, abstractmethod class UIFactory(ABC): @abstractmethod def button(self): ... @abstractmethod def checkbox(self): ... class WinFactory(UIFactory): def button(self): return WinButton() def checkbox(self): return WinCheckbox() class MacFactory(UIFactory): def button(self): return MacButton() def checkbox(self): return MacCheckbox() def paint(factory: UIFactory): # All widgets come from one family — guaranteed to match. factory.button().render() factory.checkbox().render() paint(WinFactory())
Families that must match.
Participants: an AbstractFactory interface with multiple create methods, concrete
factories (one per family), abstract products, and concrete products. Client code depends only on the
abstract factory and abstract products, so it can't accidentally mix incompatible items (a Mac button
with a Windows checkbox).
Extensibility trade-off.
- Adding a product family is easy — write one new concrete factory.
- Adding a new product type is hard — you must change the abstract factory interface and every concrete factory (an OCP tension).
- Composition, not inheritance — the client holds a factory object rather than subclassing.
- Often built from Factory Methods and frequently implemented as a Singleton.
Interview Questions
A creational pattern that provides an interface for creating families of related objects without specifying their concrete classes.
A set of products designed to work together — e.g. matching UI widgets (button, checkbox, menu) for one operating system, or a set of database access objects for one database vendor.
Creational — it abstracts the creation of whole families of objects.
A cross-platform GUI toolkit: a WindowsFactory and MacFactory each create their own styled Button and Checkbox. The app picks a factory at startup and gets a consistent look.
Because it groups several related factory methods into one object; each method creates a product, so the abstract factory is essentially a bundle of factories producing a coordinated family.
No. The client uses the abstract factory and abstract product interfaces only; the concrete factory decides which concrete products to build, keeping the client decoupled.
Give the client a different concrete factory instance (often chosen at startup/config). Since all creation goes through the factory, swapping it changes every product to the new family at once.
Factory Method creates one product via inheritance (subclass overrides a creation method). Abstract Factory creates a family of products via composition (the client holds a factory object with multiple create methods). Factory Method varies the product by subclassing the creator; Abstract Factory varies the whole family by swapping the factory object. They're related — an Abstract Factory's methods are often implemented as Factory Methods.
The abstract factory interface fixes the set of products it can create. Adding a new product type (say createSlider()) means changing that interface and then implementing the new method in every concrete factory. That's an Open/Closed violation along the product-type axis. It's the classic trade-off: easy to add new families (one new factory), hard to add new product kinds (touch all factories).
Because a family corresponds to a single concrete factory. To support a new family (e.g. a Linux GUI), you write one new concrete factory implementing the existing abstract factory interface, plus its concrete products. No existing code changes — clients still depend only on the abstract factory, so this direction respects the Open/Closed Principle.
Since a single concrete factory produces the whole family, the client can only obtain products that belong together — you physically can't get a Mac button and a Windows checkbox from the same factory. This guarantees compatible combinations at the design level, which is a key reason to choose it over ad-hoc creation where mismatched products could be assembled by mistake.
Commonly, yes. An application usually needs just one instance of a given concrete factory, so it's frequently exposed as a singleton (or a single DI-managed instance). This isn't required by the pattern, but it's a natural fit since the chosen family is typically global for the app's run.
Typically by a small piece of configuration/bootstrapping logic: read an environment/OS/config value and instantiate the matching factory once, then pass it to clients (often via DI). After that single decision point, all creation is polymorphic through the abstract factory, so the rest of the code has no conditionals about the family.
Java's javax.xml.parsers.DocumentBuilderFactory and SAXParserFactory, javax.xml.transform.TransformerFactory, and JDBC-style connection factories create related objects without exposing implementations. GUI toolkits and look-and-feel systems (e.g. Swing's pluggable L&F) also embody the idea of swapping a family of components.
Options to soften the "hard to add products" problem: (1) use a more generic creation method like create(productType) returning a base product, trading compile-time type safety for flexibility (you can add product kinds without changing the interface, but clients must cast/know types); (2) provide default implementations (Java default methods) on the abstract factory so new methods don't break existing concrete factories; (3) split the abstract factory into smaller interfaces (ISP) so a new product type is a new interface some factories implement, rather than bloating one; or (4) use a registry/reflection-driven approach keyed by (family, productType). Each trades some of the pattern's strong typing and guaranteed-family-consistency for extensibility, so the choice depends on whether new product types or new families are the more frequent axis of change.
DIP: client code (high-level policy) depends only on the abstract factory and abstract product interfaces; concrete factories/products (low-level details) implement those abstractions, so dependencies point toward abstractions. OCP: along the family axis it's open for extension (add a factory) and closed for modification (no client/existing-factory edits). The single bootstrap point that selects the concrete factory is the only place that names concretes — everything else is abstraction-only. This makes the pattern a textbook realization of "depend on abstractions, extend by adding implementations," which is why it underpins pluggable/skinnable systems. The caveat is that OCP holds strongly for families but weakly for product-type additions, so the design optimizes one axis of change.
Abstract Factory is about creating families of related, relatively simple objects and swapping the family. Prefer Builder when a single object is complex to construct (many optional parts, step-by-step assembly, different representations) — Builder focuses on how one product is built, not which family it belongs to. Prefer Prototype when creating objects by cloning existing instances is cheaper or more flexible than constructing from scratch, or when the concrete types are decided at runtime and you'd rather copy a configured exemplar than maintain a factory hierarchy. They can even combine: an Abstract Factory might use Prototype internally (clone registered prototypes to produce family members) or use Builders to assemble complex products. The discriminator is the shape of the creation problem: family/consistency (Abstract Factory), complex assembly (Builder), or cloning/configurable exemplars (Prototype).
It's a direct instance of the expression problem's asymmetry. Treating "families" as one axis and "product types" as the other: Abstract Factory makes adding new families (like adding new data variants) trivial and additive, while adding new operations/product types requires touching every existing factory (editing the shared abstraction and all implementers). This mirrors how OO polymorphism eases new types but complicates new operations. Recognizing this tells you Abstract Factory is the right tool only when the product-type set is stable and families vary; if product types churn more than families, the pattern fights you, and a different decomposition (e.g. generic creation, visitor-like operations, or splitting interfaces) better matches the real axis of change. The pattern doesn't escape the fundamental trade-off; it just picks a side.
The abstraction is a natural test seam: inject a test/fake factory that returns stub or mock products, letting you drive client logic without real (possibly heavy) concrete products. You can verify the client requests the expected products and behaves correctly given controlled product behavior. Separately, test each concrete factory to confirm it returns the correct concrete family, and test each product against its interface contract (ideally a shared contract-test suite run across all families to ensure substitutability/LSP). Because the client depends on abstractions, you avoid brittle setup and can simulate any family — one of the pattern's testability wins. The main pitfall is factories exposed as global singletons, which reintroduce global-state testing problems; prefer injecting the factory to keep tests isolated.