Difference Between Factory Method and Abstract Factory?
Both patterns help create objects, but at different levels:
Junior Level
Both patterns help create objects, but at different levels:
Factory Method — creates one type of object:
// Factory method creates a single product
interface Button { void render(); }
class WinButton implements Button { ... }
class MacButton implements Button { ... }
abstract class Dialog {
// Factory Method — subclass decides which button to create
abstract Button createButton();
}
Abstract Factory — creates a family of related objects:
// Abstract factory creates a whole family of products
// Related = they must be from the same "family" (all Windows components or all Mac components),
// otherwise the UI will look inconsistent.
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
Menu createMenu();
}
class WinFactory implements GUIFactory {
Button createButton() { return new WinButton(); }
Checkbox createCheckbox() { return new WinCheckbox(); }
Menu createMenu() { return new WinMenu(); }
}
Key difference:
- Factory Method = one product (button)
- Abstract Factory = family of products (button + checkbox + menu)
Middle Level
OCP (Open/Closed Principle) — open for extension, closed for modification.
Factory Method
Mechanism: Inheritance (subclasses decide)
// Abstract class with Factory Method
public abstract class PaymentService {
// Template method
public void processPayment() {
PaymentGateway gateway = createGateway(); // Factory Method
gateway.authorize();
gateway.capture();
}
// Subclass implements creation
abstract PaymentGateway createGateway();
}
// Concrete implementations
public class CreditCardService extends PaymentService {
@Override
PaymentGateway createGateway() {
return new StripeGateway(); // Subclass decides
}
}
public class PayPalService extends PaymentService {
@Override
PaymentGateway createGateway() {
return new PayPalGateway();
}
}
When to use:
- Need to extend the system with new types
- Class doesn’t know which objects to create
- Creation is delegated to subclasses
Abstract Factory
Mechanism: Composition (objects are passed in)
// Factory interface
public interface DatabaseFactory {
Connection createConnection();
Statement createStatement();
ResultSet createResultSet();
}
// Concrete factory for MySQL
public class MySQLFactory implements DatabaseFactory {
public Connection createConnection() { return new MySQLConnection(); }
public Statement createStatement() { return new MySQLStatement(); }
public ResultSet createResultSet() { return new MySQLResultSet(); }
}
// Concrete factory for PostgreSQL
public class PostgresFactory implements DatabaseFactory {
public Connection createConnection() { return new PostgresConnection(); }
public Statement createStatement() { return new PostgresStatement(); }
public ResultSet createResultSet() { return new PostgresResultSet(); }
}
// Client works with any factory
public class DatabaseService {
private final DatabaseFactory factory;
public DatabaseService(DatabaseFactory factory) {
this.factory = factory; // Pass the needed factory
}
public void query() {
Connection conn = factory.createConnection();
Statement stmt = factory.createStatement();
// All objects are compatible!
}
}
When to use:
- Need to create a family of related objects
- Important that objects are from the same family
- Client should not know about concrete classes
Comparison
| Criterion | Factory Method | Abstract Factory |
|---|---|---|
| Creates | One object | Family of objects |
| Mechanism | Inheritance | Composition |
| Extension | New subclass | New factory |
| Complexity | Low | High |
| OCP | Complies | Violated when adding a product |
Typical Mistakes
- Abstract Factory for a single product
// Overengineering interface ButtonFactory { Button create(); } // Factory Method is sufficient abstract class Dialog { abstract Button createButton(); } - OCP violation in Abstract Factory
// Added a new product -> break ALL factories interface GUIFactory { Button createButton(); Checkbox createCheckbox(); Tooltip createTooltip(); // <- New! } // All implementations must be changed!
Senior Level
Architectural Scope
Factory Method = extension point in a hierarchy:
Dialog (abstraction)
|-- createButton() <- extension point
| |-- WinButton
| +-- MacButton
+-- Template method uses createButton()
Abstract Factory = compatibility boundary:
GUIFactory (family boundary)
|-- WinFactory -> WinButton + WinCheckbox + WinMenu
+-- MacFactory -> MacButton + MacCheckbox + MacMenu
Guarantee: products from different families do NOT mix!
Open/Closed Principle Trade-offs
Factory Method complies with OCP:
// Add a new type -> new subclass (don't change existing code)
class CryptoService extends PaymentService {
@Override
PaymentGateway createGateway() {
return new CoinbaseGateway();
}
}
// Existing code unchanged
Abstract Factory violates OCP on extension:
// Add a new product -> change interface -> break ALL implementations
interface GUIFactory {
Button createButton();
Slider createSlider(); // <- New product
}
// All factories must be updated:
class WinFactory implements GUIFactory {
Slider createSlider() { return new WinSlider(); } // <- Must add!
}
class MacFactory implements GUIFactory {
Slider createSlider() { return new MacSlider(); } // <- Must add!
}
// Existing code changed
System Evolution
Simple Factory (static method)
-> (need extensibility)
Factory Method (inheritance)
-> (need multiple products)
Abstract Factory (families)
-> (need flexibility)
DI Container (Spring)
Simple Factory vs Factory Method
Simple Factory = static method. Cannot be extended via inheritance. Factory Method = virtual method in subclass. Can be extended.
Modern Java Implementations
Factory Method -> Supplier:
// Instead of inheritance
public class Dialog {
private final Supplier<Button> buttonFactory;
public Dialog(Supplier<Button> buttonFactory) {
this.buttonFactory = buttonFactory;
}
public void render() {
Button button = buttonFactory.get();
button.render();
}
}
// Usage
Dialog dialog = new Dialog(WinButton::new);
Abstract Factory -> Records:
// Record for storing a family
public record GUIFactory(
Supplier<Button> button,
Supplier<Checkbox> checkbox,
Supplier<Menu> menu
) {}
// Predefined factories
public static final GUIFactory WINDOWS = new GUIFactory(
WinButton::new, WinCheckbox::new, WinMenu::new
);
public static final GUIFactory MAC = new GUIFactory(
MacButton::new, MacCheckbox::new, MacMenu::new
);
Spring Context as Meta-Factory
// Spring itself decides which beans to create
@Configuration
public class DatabaseConfig {
@Bean
@Profile("mysql")
public DatabaseFactory mysqlFactory() {
return new MySQLFactory();
}
@Bean
@Profile("postgres")
public DatabaseFactory postgresFactory() {
return new PostgresFactory();
}
}
// Spring = Abstract Factory on steroids
// + Profile = family selection at runtime
Performance Implications
Factory Method:
Monomorphic call (1 subclass) -> inlining
Bimorphic call (2 subclasses) -> still fast
Megamorphic call (>2 subclasses) -> indirect call
Abstract Factory:
Additional level of indirection:
client -> factory interface -> concrete factory -> product
Overhead: 2 virtual calls instead of 1
Production Experience
Real scenario: Abstract Factory prevented mixing
- UI framework: Windows and Mac themes
- Problem: developers were mixing components
- Solution: Abstract Factory guarantees compatibility
- Result: impossible to create MacButton in Windows theme
Best Practices
- Factory Method for a single extensible product
- Abstract Factory for a family of related products
- **Supplier
** instead of Factory Method in Modern Java
**Supplier
- Spring Profiles instead of manual Abstract Factory
- Avoid Abstract Factory if there’s only one family
- Remember OCP violation when extending Abstract Factory
- Record for storing factory families
Records — Java 16+ compact immutable classes.
Senior Summary
- Factory Method = inheritance, one product, OCP-friendly
- Abstract Factory = composition, family of products, OCP violation
- Evolution: Simple -> Factory Method -> Abstract Factory -> DI
- Modern Java: Supplier
replaces Factory Method - Spring = Meta-Factory with Profiles
- OCP Trade-off: Adding a new product to Abstract Factory requires changing ALL factory implementations. If there are 10 factories — 10 files to edit.
- Guarantee: Abstract Factory prevents mixing products
Interview Cheat Sheet
Must know:
- Factory Method creates one product via inheritance, Abstract Factory — a family of products via composition
- Factory Method complies with OCP (new subclass doesn’t change code), Abstract Factory violates OCP when adding a new product
- Evolution: Simple Factory -> Factory Method -> Abstract Factory -> DI Container (Spring)
- In Modern Java: Factory Method is replaced by Supplier
, Abstract Factory — by Records or Map<Enum, Supplier> - Spring Context = Meta-Factory with @Profiles for family selection at runtime
- Megamorphic calls: >2 subclasses in Factory Method -> JIT cannot inline
- Abstract Factory guarantees: products from different families do NOT mix
Common follow-up questions:
- When to choose Factory Method vs Abstract Factory? — One product = Factory Method, family of related = Abstract Factory
- Why does Abstract Factory violate OCP? — Adding a new product requires changing the interface -> ALL implementations must be updated
- How does Simple Factory differ from Factory Method? — Simple Factory = static method (cannot extend), Factory Method = virtual method in subclass
- How does Spring replace Abstract Factory? — @Configuration + @Profile = bean family selection at runtime
Red flags (DO NOT say):
- “I use Abstract Factory for a single product” — overengineering, Factory Method is enough
- “Factory Method and Abstract Factory are the same” — fundamentally different mechanisms and goals
- “Abstract Factory complies with OCP” — it violates OCP when adding a new product
- “Spring doesn’t need Factory patterns” — Spring itself uses Abstract Factory under the hood
Related topics:
- [[08. When to use Builder]] — creational pattern for complex objects
- [[09. What is Prototype pattern]] — creational copying pattern
- [[01. What are design patterns]] — general introduction
- [[02. What pattern categories exist]] — Creational patterns
- [[10. When to use Strategy]] — behavioral pattern, composition-based alternative