The Problem
Some applications need families of related values to change together. An admin console, a public storefront, and an internal backoffice may all expose the same capabilities, but with different concrete widgets, formatting rules, or integrations. If callers build those parts independently, the family can drift into inconsistent combinations.
The Solution
Abstract Factory centralizes creation for a compatible family of objects. In Go, that usually means a small factory interface plus ordinary constructor methods. The caller asks for abstract behavior such as a checkout button or a status badge, while the chosen factory decides which concrete family to return.
Structure
- Abstract factory:
UIThemeFactorycreates a related set of UI components. - Abstract products:
CheckoutButtonandStatusBadgedefine the behavior the caller needs. - Concrete factories: Storefront and admin factories each produce a consistent family.
- Concrete products: Each family renders itself differently while satisfying the same contracts.
- Client: Application code receives one factory and builds a coherent set of components.
Implementation
This example uses two UI themes for the same commerce workflow. The client swaps a single factory to render either a customer-facing storefront or an operator-facing admin console without changing any downstream code.
package main
type CheckoutButton interface {
Render() string
}
type StatusBadge interface {
Render() string
}
type UIThemeFactory interface {
CreateCheckoutButton() CheckoutButton
CreateStatusBadge(status string) StatusBadge
} Best Practices
- Keep the product interfaces narrow so whole families remain easy to swap.
- Prefer a factory only when objects truly vary as a coordinated family, not as unrelated one-off constructors.
- Return interfaces from the factory, but keep concrete types simple and idiomatic inside the package.
- Use Abstract Factory with dependency injection so the family can be selected at startup or in tests.
- Avoid creating a giant factory with dozens of unrelated methods. Split by bounded context when families stop moving together.
When to Use
- Multiple related objects must be selected together as a compatible set.
- You want to swap whole implementations for theme, environment, tenant, or provider concerns.
- The client should stay unaware of the concrete types that make up the chosen family.
When NOT to Use
- Only one object varies and a plain constructor or Factory Method is enough.
- The factory would become a dumping ground for unrelated object creation.
- The extra indirection would hide simple code without reducing coupling.