1. Home
  2. /
  3. Docs
  4. /
  5. Design Pattern
  6. /
  7. Creational
  8. /
  9. Factory

Factory

What is the Factory Pattern?

The Factory Pattern is like ordering food at a restaurant. You don’t go into the kitchen and cook your meal yourself – you simply tell the waiter what you want, and the kitchen creates it for you. You get your food without needing to know the recipe, ingredients, or cooking techniques. That’s exactly what the Factory Pattern does in programming.

In technical terms, the Factory Pattern is a creational design pattern that provides an interface for creating objects without specifying their exact classes. It delegates the instantiation logic to specialized factory classes or methods, keeping your code flexible and maintainable.

The Restaurant Analogy

Let’s expand on the restaurant analogy to really understand this pattern:

Imagine you walk into a restaurant and order “a vegetarian meal.” The waiter doesn’t bring you ingredients and a recipe – they bring you a complete, ready-to-eat dish. Behind the scenes, the kitchen (factory) decided whether to make you pasta, a salad, or a veggie burger based on the restaurant’s menu and your request.

The key benefits here:

  • You don’t need to know how to cook
  • You don’t need to know what ingredients are available
  • The restaurant can change recipes without you noticing
  • You just get what you asked for

Types of Factory Patterns

There are three variations of the Factory Pattern, each serving different needs:

graph LR
    A[Factory Patterns]
    
    A --> B[Simple Factory]
    B --> B1[Single factory class creates objects]
    B --> B2[Not a formal pattern but widely used]
    
    A --> C[Factory Method]
    C --> C1[Defines interface for creation]
    C --> C2[Subclasses decide what to create]
    
    A --> D[Abstract Factory]
    D --> D1[Creates families of related objects]
    D --> D2[Factory of factories]
    
    style A fill:#4a90e2,color:#fff
    style B fill:#7cb342,color:#fff
    style C fill:#fb8c00,color:#fff
    style D fill:#ab47bc,color:#fff

Simple Factory (Factory Pattern)

The Simple Factory is the most straightforward version. Think of it as a vending machine – you press a button (pass a parameter), and it gives you the product you requested.

Structure

classDiagram
    class Product {
        <>
        +operation()
    }
    
    class ConcreteProductA {
        +operation()
    }
    
    class ConcreteProductB {
        +operation()
    }
    
    class SimpleFactory {
        +createProduct(type)
    }
    
    class Client {
        +useProduct()
    }
    
    Product <|.. ConcreteProductA
    Product <|.. ConcreteProductB
    SimpleFactory ..> Product: creates
    Client --> SimpleFactory: uses
    Client --> Product: uses

How It Works

The Simple Factory has a single method that creates objects based on input parameters. It centralizes the creation logic in one place.

Pseudo Code

// Product Interface
interface Vehicle:
    method drive()
    method getType()

// Concrete Products
class Car implements Vehicle:
    method drive():
        print "Driving a car on the road"
    method getType():
        return "Car"

class Motorcycle implements Vehicle:
    method drive():
        print "Riding a motorcycle"
    method getType():
        return "Motorcycle"

class Truck implements Vehicle:
    method drive():
        print "Driving a heavy truck"
    method getType():
        return "Truck"

// Simple Factory
class VehicleFactory:
    method createVehicle(type):
        if type == "car":
            return new Car()
        else if type == "motorcycle":
            return new Motorcycle()
        else if type == "truck":
            return new Truck()
        else:
            throw Error("Unknown vehicle type")

// Client Usage
factory = new VehicleFactory()
vehicle = factory.createVehicle("car")
vehicle.drive()

Real-World Use Cases

  • Document Generators: Creating different document types (PDF, Word, Excel) based on user selection
  • Payment Processing: Creating payment handlers (Credit Card, PayPal, Stripe) based on user choice
  • Logging Systems: Creating different loggers (File, Database, Console) based on configuration
  • Image Processors: Creating handlers for different image formats (JPEG, PNG, GIF)

Factory Method Pattern

The Factory Method is more sophisticated. Imagine a franchise restaurant – each location has its own kitchen (factory method) that follows the company’s recipe guidelines but can customize dishes for local tastes. The interface is the same, but each location decides exactly what to create.

The Key Difference

Unlike Simple Factory where one class creates everything, Factory Method lets subclasses decide what to create. It defines an interface for creation but lets child classes choose which class to instantiate.

Structure

classDiagram
    class Creator {
        <>
        +factoryMethod()
        +someOperation()
    }
    
    class ConcreteCreatorA {
        +factoryMethod()
    }
    
    class ConcreteCreatorB {
        +factoryMethod()
    }
    
    class Product {
        <>
        +operation()
    }
    
    class ConcreteProductA {
        +operation()
    }
    
    class ConcreteProductB {
        +operation()
    }
    
    Creator <|-- ConcreteCreatorA
    Creator <|-- ConcreteCreatorB
    Product <|.. ConcreteProductA
    Product <|.. ConcreteProductB
    ConcreteCreatorA ..> ConcreteProductA: creates
    ConcreteCreatorB ..> ConcreteProductB: creates
    Creator ..> Product: uses

Flow Diagram

sequenceDiagram
    participant Client
    participant Creator
    participant ConcreteCreator
    participant Product
    
    Client->>ConcreteCreator: someOperation()
    ConcreteCreator->>ConcreteCreator: factoryMethod()
    ConcreteCreator->>Product: create instance
    Product-->>ConcreteCreator: return product
    ConcreteCreator->>Product: use product
    ConcreteCreator-->>Client: return result

Pseudo Code

// Product Interface
interface Notification:
    method send(message)

// Concrete Products
class EmailNotification implements Notification:
    method send(message):
        print "Sending email: " + message

class SMSNotification implements Notification:
    method send(message):
        print "Sending SMS: " + message

class PushNotification implements Notification:
    method send(message):
        print "Sending push notification: " + message

// Creator (Abstract Class)
abstract class NotificationService:
    // Factory Method - to be implemented by subclasses
    abstract method createNotification(): Notification
    
    // Business logic using the factory method
    method notify(message):
        notification = this.createNotification()
        notification.send(message)

// Concrete Creators
class EmailNotificationService extends NotificationService:
    method createNotification():
        return new EmailNotification()

class SMSNotificationService extends NotificationService:
    method createNotification():
        return new SMSNotification()

class PushNotificationService extends NotificationService:
    method createNotification():
        return new PushNotification()

// Client Usage
service = new EmailNotificationService()
service.notify("Hello from Factory Method!")

// Can easily switch to different notification type
smsService = new SMSNotificationService()
smsService.notify("Hello via SMS!")

Real-World Use Cases

  • UI Frameworks: Creating platform-specific UI components (Windows buttons vs Mac buttons)
  • Database Connections: Creating different database connectors (MySQL, PostgreSQL, MongoDB)
  • Export Functions: Creating different exporters in applications (PDF exporter, Excel exporter)
  • Game Development: Creating different enemy types based on game level or difficulty
  • Plugin Systems: Loading and creating different plugin implementations dynamically

When to Use Factory Pattern

flowchart TD
    A[Need to create objects?] --> B{Know exact type at compile time?}
    B -->|Yes| C[Direct instantiation is fine]
    B -->|No| D{Creation logic complex?}
    D -->|No| E{Multiple related types?}
    D -->|Yes| F[Use Factory Pattern]
    E -->|No| C
    E -->|Yes| F
    F --> G{Need subclass flexibility?}
    G -->|Yes| H[Use Factory Method]
    G -->|No| I[Use Simple Factory]
    
    style F fill:#c8e6c9
    style H fill:#c8e6c9
    style I fill:#c8e6c9
    style C fill:#ffcdd2

Consider using the Factory Pattern when:

  • You don’t know beforehand the exact types of objects your code will work with
  • You want to provide a library where users can extend internal components
  • You want to save system resources by reusing existing objects instead of rebuilding them
  • Object creation involves complex logic that shouldn’t be repeated
  • You need to decouple object creation from usage

Real-World Scenario: Notification System

Let’s walk through a practical example – building a notification system for an e-commerce application.

The Problem

Your e-commerce platform needs to send notifications through multiple channels:

  • Email for order confirmations
  • SMS for delivery updates
  • Push notifications for promotional offers
  • In-app messages for account updates

Without Factory Pattern, you might write something like this everywhere:

// Bad approach - repeated logic everywhere
if notificationType == "email":
    notification = new EmailNotification()
    notification.setServer(emailServer)
    notification.setCredentials(credentials)
else if notificationType == "sms":
    notification = new SMSNotification()
    notification.setProvider(smsProvider)
    notification.setApiKey(apiKey)
// ... and so on

The Solution with Factory Pattern

// Factory handles all the complexity
class NotificationFactory:
    method createNotification(type, config):
        switch type:
            case "email":
                notification = new EmailNotification()
                notification.configure(config.emailSettings)
                return notification
            case "sms":
                notification = new SMSNotification()
                notification.configure(config.smsSettings)
                return notification
            case "push":
                notification = new PushNotification()
                notification.configure(config.pushSettings)
                return notification
            default:
                throw Error("Unknown notification type")

// Client code is now clean and simple
factory = new NotificationFactory()
notification = factory.createNotification("email", config)
notification.send("Your order has been confirmed!")

Benefits in This Scenario

  • Centralized Logic: All notification creation logic is in one place
  • Easy to Extend: Adding WhatsApp notifications? Just add one case in the factory
  • Easy to Test: Mock the factory to test different notification scenarios
  • Clean Client Code: The rest of your code doesn’t need to know implementation details

Benefits of Factory Pattern

  • Loose Coupling: Client code doesn’t depend on concrete classes, only interfaces
  • Single Responsibility: Creation logic is separated from business logic
  • Open/Closed Principle: Easy to add new product types without modifying existing code
  • Easier Testing: Can easily mock or stub objects in tests
  • Code Reusability: Factory logic is reused across the application
  • Flexibility: Can change what gets created without affecting client code

Potential Drawbacks

  • Increased Complexity: Adds more classes and interfaces to your codebase
  • Indirection: Extra layer between client and concrete classes can make code harder to follow
  • Overhead: May be overkill for simple object creation scenarios
  • Learning Curve: Team members need to understand the pattern to maintain code effectively

Factory Pattern vs Direct Instantiation

Here’s when to use each approach:

ScenarioDirect InstantiationFactory Pattern
Simple object creation✓ Use thisOverkill
Type known at compile time✓ Use thisNot needed
Complex creation logicAvoid✓ Use this
Type determined at runtimeDifficult✓ Use this
Multiple related typesMessy✓ Use this
Need to extend typesHard to maintain✓ Use this

Common Mistakes to Avoid

  1. Overusing the Pattern: Don’t make everything a factory. Simple object creation doesn’t need it.
  2. God Factory: Avoid creating one giant factory that creates every type in your system. Keep factories focused.
  3. Ignoring Error Handling: Always handle cases where the requested type doesn’t exist.
  4. Tight Coupling in Factory: The factory itself shouldn’t have too many dependencies.
  5. Not Using Interfaces: Products should implement common interfaces for true flexibility.

Best Practices

  1. Return Interfaces, Not Concrete Classes: Factory methods should return interface types
  2. Keep Factories Simple: Don’t add business logic to factories – they should only create objects
  3. Use Dependency Injection: Pass configuration to factories rather than hardcoding
  4. Consider Registration: For extensible systems, let products register themselves with the factory
  5. Document Type Parameters: Clearly document what types the factory can create
  6. Thread Safety: Consider thread safety if factories are used in multi-threaded environments

Combining with Other Patterns

Factory Pattern works well with other design patterns:

  • Singleton + Factory: Make the factory itself a singleton to ensure consistent object creation
  • Prototype + Factory: Factory can clone prototypes instead of creating from scratch
  • Strategy + Factory: Factory creates different strategy implementations
  • Dependency Injection + Factory: Inject factories to provide flexible object creation

Decision Guide

flowchart TD
    A[Need object creation abstraction?] --> B{Simple or Complex?}
    B -->|Simple| C{Few types?}
    B -->|Complex| D[Use Factory Method]
    C -->|Yes, 2-5 types| E[Use Simple Factory]
    C -->|No, many types| F{Need families?}
    F -->|Yes| G[Consider Abstract Factory]
    F -->|No| D
    
    style E fill:#c8e6c9
    style D fill:#c8e6c9
    style G fill:#fff9c4

Key Takeaways

  • Factory Pattern provides a way to create objects without specifying exact classes
  • Simple Factory centralizes creation logic in one class
  • Factory Method delegates creation decisions to subclasses
  • Use it when you need flexibility in what gets created
  • It promotes loose coupling and follows SOLID principles
  • Don’t overuse it for simple scenarios where direct instantiation works fine
  • Real-world applications: payment systems, notification services, document generators, plugin architectures

The Factory Pattern is one of the most widely used design patterns in software development. Understanding when and how to apply it will significantly improve your code’s flexibility and maintainability. In the next post, we’ll explore actual code implementations across different programming languages.

Articles

Still stuck? Contact

How can we help?

Leave a Reply

Your email address will not be published. Required fields are marked *

All Rights Reserved 2025.