Simple Factory
A Simple Factory encapsulates object creation logic in a single method. It's not a GoF pattern but widely used.
Basic Implementation
// Simple Factory
public class NotificationFactory {
public static Notification create(NotificationType type) {
return switch (type) {
case EMAIL -> new EmailNotification();
case SMS -> new SMSNotification();
case PUSH -> new PushNotification();
};
}
}
// Usage
Notification notification = NotificationFactory.create(NotificationType.EMAIL);
notification.send("Hello!");
When to Use
- You need a single method to create different types
- Object creation logic is complex
- You want to centralize creation decisions
- Different conditions determine which object to create
Advantages
- Encapsulation: Client doesn't need to know concrete classes
- Centralization: Creation logic in one place
- Flexibility: Easy to add new types
- Readability: Clear intent
Limitations
- Violation of Open-Closed: Adding new types requires modifying factory
- Single responsibility: Factory has too many creation methods
Example: Payment Processing
public class PaymentProcessorFactory {
public static PaymentProcessor create(PaymentType type) {
return switch (type) {
case CREDIT_CARD -> new CreditCardProcessor();
case PAYPAL -> new PayPalProcessor();
case BITCOIN -> new BitcoinProcessor();
};
}
}
// Client code
PaymentProcessor processor = PaymentProcessorFactory.create(user.getPaymentType());
processor.processPayment(order.getTotal());
Factory Method
Factory Method defines an interface for creating objects but lets subclasses decide which class to instantiate.
Implementation
// Creator abstract class
public abstract class NotificationSender {
// Factory Method
protected abstract Notification createNotification();
public void sendNotification(String message) {
Notification notification = createNotification();
notification.send(message);
}
}
// Concrete creators
class EmailSender extends NotificationSender {
@Override
protected Notification createNotification() {
return new EmailNotification();
}
}
class SMSSender extends NotificationSender {
@Override
protected Notification createNotification() {
return new SMSNotification();
}
}
// Usage
NotificationSender sender = new EmailSender();
sender.sendNotification("Hello!");
How It Works
NotificationSender (abstract)
│
│ + sendNotification(message)
│ │
│ └── createNotification() ← Factory Method
│ ▲ (abstract)
│ │
├─────────┴──────────┐
│ │
EmailSender SMSSender
│ │
└── createNotification() └── createNotification()
returns EmailNotification returns SMSNotification
When to Use
- A class can't anticipate the type of objects it needs to create
- You want subclasses to specify the objects to create
- You need to delegate creation responsibility to subclasses
Real-World Example
// Document types
abstract class Document {
abstract Page createPage();
}
class Resume extends Document {
Page createPage() { return new ResumePage(); }
}
class Report extends Document {
Page createPage() { return new ReportPage(); }
}
// Creator
abstract class DocumentFactory {
abstract Document createDocument();
void printDocument() {
Document doc = createDocument();
// Process document...
}
}
Abstract Factory
Abstract Factory provides an interface for creating families of related objects without specifying their concrete classes.
Implementation
// Abstract Factory
public interface GUIFactory {
Button createButton();
TextBox createTextBox();
CheckBox createCheckBox();
}
// Concrete Factories
public class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public TextBox createTextBox() { return new WindowsTextBox(); }
public CheckBox createCheckBox() { return new WindowsCheckBox(); }
}
public class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public TextBox createTextBox() { return new MacTextBox(); }
public CheckBox createCheckBox() { return new MacCheckBox(); }
}
// Usage
GUIFactory factory = isWindows() ? new WindowsFactory() : new MacFactory();
Button button = factory.createButton();
button.render();
Family of Objects
GUIFactory
├── WindowsFactory
│ ├── WindowsButton
│ ├── WindowsTextBox
│ └── WindowsCheckBox
│
└── MacFactory
├── MacButton
├── MacTextBox
└── MacCheckBox
All objects from the same factory are compatible
When to Use
- System must be independent of how objects are created
- System must work with multiple families of objects
- You need to enforce constraints about which objects are used together
Example: Database Abstraction
public interface DatabaseFactory {
Connection createConnection();
QueryBuilder createQueryBuilder();
MigrationRunner createMigrationRunner();
}
public class PostgresFactory implements DatabaseFactory {
public Connection createConnection() { return new PostgresConnection(); }
public QueryBuilder createQueryBuilder() { return new PostgresQueryBuilder(); }
public MigrationRunner createMigrationRunner() { return new PostgresMigration(); }
}
public class MySQLFactory implements DatabaseFactory {
public Connection createConnection() { return new MySQLConnection(); }
public QueryBuilder createQueryBuilder() { return new MySQLQueryBuilder(); }
public MigrationRunner createMigrationRunner() { return new MySQLMigration(); }
}
When to Use
Choosing the right factory pattern depends on the specific problem you're solving.
Decision Matrix
┌─────────────────────────────────────────────────────────────┐
│ Factory Pattern Selection │
├─────────────────────────────────────────────────────────────┤
│ │
│ Simple Factory: │
│ - Single creation method │
│ - Don't need subclass flexibility │
│ - Simple switch/if-else creation │
│ │
│ Factory Method: │
│ - Subclass decides which class to instantiate │
│ - You don't know exact types beforehand │
│ - Want to delegate creation to subclasses │
│ │
│ Abstract Factory: │
│ - Need families of related objects │
│ - Objects must be used together │
│ - Multiple product variants │
│ │
└─────────────────────────────────────────────────────────────┘
Comparison Table
| Aspect | Simple Factory | Factory Method | Abstract Factory |
|---|---|---|---|
| GoF Pattern | No | Yes | Yes |
| Creation | Single method | Subclass method | Interface |
| Flexibility | Moderate | High | Very High |
| Complexity | Low | Medium | High |
| Adding types | Modify factory | Add subclass | Add factory |
Common Use Cases
| Use Case | Pattern |
|---|---|
| Different notification types | Simple Factory |
| Document format creation | Factory Method |
| Cross-platform UI components | Abstract Factory |
| Payment processor selection | Simple Factory |
| Plugin loading | Factory Method |
| Database driver creation | Abstract Factory |
Anti-Patterns
- Overuse: Don't use factory when
newis sufficient - God Factory: One factory creating everything
- Leaking types: Factory returns concrete type instead of interface
- Complex conditions: Too many if/else in factory method
Refactoring to Factory
// Before: scattered creation
public class OrderService {
public void processPayment(Order order) {
if (order.getPaymentType() == CREDIT_CARD) {
new CreditCardProcessor().process(order);
} else if (order.getPaymentType() == PAYPAL) {
new PayPalProcessor().process(order);
}
}
}
// After: centralized in factory
public class OrderService {
private final PaymentProcessorFactory factory;
public void processPayment(Order order) {
factory.create(order.getPaymentType()).process(order);
}
}
Practice Problems
Design a scalable Factory Pattern system. Cover high-level architecture, data model, and API design.
Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliabilityHow would you scale Factory Pattern to handle 10x the current load? Identify bottlenecks and solutions.
Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decompositionAnalyze potential failure modes for Factory Pattern and design mitigation strategies.
Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradationQuiz
1. What is the difference between Simple Factory and Factory Method?
2. When should you use Abstract Factory?
3. What problem does Factory Method solve?
4. What is an anti-pattern for factory usage?
5. What is a Simple Factory limitation?
Flashcards
Question
What is a Simple Factory?
Click to reveal answer
Answer
A single method that encapsulates object creation logic. Not a GoF pattern but widely used. Centralizes creation decisions.
Question
What is Factory Method?
Click to reveal answer
Answer
Defines an interface for creating objects but lets subclasses decide which class to instantiate. Uses abstract creation method.
Question
What is Abstract Factory?
Click to reveal answer
Answer
Provides an interface for creating families of related objects without specifying concrete classes. Ensures compatibility between created objects.
Question
When to use Factory Method vs Abstract Factory?
Click to reveal answer
Answer
Factory Method: subclass decides single object. Abstract Factory: create families of related objects that must be compatible.
Question
What is a factory anti-pattern?
Click to reveal answer
Answer
Revision Notes
Key Takeaways
- 1.Simple Factory centralizes creation in a single method
- 2.Factory Method lets subclasses decide which class to instantiate
- 3.Abstract Factory creates families of related compatible objects
- 4.Choose based on flexibility needs and object relationships
- 5.Don't overuse factories — use `new` when sufficient
Interview Tips
- •Explain which factory pattern fits the problem and why
- •Show how factories enable adding new types without modifying client code
- •Discuss how factories support testing through dependency injection
- •Mention when NOT to use factories (simple creation scenarios)
Cheat Sheet
Factory Pattern - Cheat Sheet
Simple Factory:
- Single creation method
- switch/if-else for types
- Not GoF pattern
- Violates OCP when adding types
Factory Method:
- Abstract creation method
- Subclasses decide class
- GoF pattern
- Flexible, extensible
Abstract Factory:
- Interface for object families
- Related objects must be compatible
- GoF pattern
- Multiple product variants
Selection:
| Need | Pattern |
|---|---|
| Simple creation | Simple Factory |
| Subclass decides | Factory Method |
| Object families | Abstract Factory |
Use When:
- Don't know exact types
- Complex creation logic
- Need flexibility
- Objects must be compatible