Factory Design Pattern


Here, we will see how the Factory Design Pattern can be applied to the creation of different types of documents and Transport system with example.

Factory Design Pattern Introduction

The Factory Pattern is a creational design pattern that provides an interface for creating objects without specifying their exact class. The factory method encapsulates object creation, making it easier to manage and modify. This pattern allows for decoupling the code that uses the objects from the code that creates them.

Advantages of the Factory Pattern

  1. Decoupling - It separates the object creation logic from the main business logic, reducing dependency and making the system more modular.
  2. Flexibility - You can introduce new classes without modifying the client code. This improves scalability and maintainability.
  3. Simplifies Code - Instead of spreading object creation logic throughout the system, it centralizes it in a factory, which makes the code more readable and manageable.
  4. Object Reusability - It allows for reusing existing objects when applicable, reducing memory consumption.
  5. Promotes Interface-Based Programming - Encourages the use of interfaces or abstract classes, improving code extensibility.

When to Use the Factory Pattern

  1. Complex Object Creation - When creating objects is complex, involves multiple steps, or requires specific configuration.
  2. Switching Between Related Objects - When a system needs to switch between different related classes dynamically.
  3. Code that Depends on Interfaces - When working with abstractions (interfaces or abstract classes) and the specific implementation should be hidden.
  4. Needing Centralized Object Management - When object creation needs to be managed and controlled from a central point, like in dependency injection scenarios.

Problems - A document system without Factory

Scenario: A common real-world example of the Factory Design Pattern is the creation of different types of documents in a document processing application. Consider a scenario where you have a document editor application that can create different types of documents, such as Resume, Report, and Letter.

If a factory pattern is not used in a document generation system, several problems can arise.

Problems

  • Tight Coupling - Without the Factory Method pattern, the code that creates documents would need to know the exact classes (e.g. Resume, Report). This makes the system tightly coupled and harder to extend.
  • Difficulty in Adding New Document Types - If a new document type is needed (e.g., Excel), you would have to modify the existing code to accommodate the new class. This violates the Open/Closed Principle (OCP), which states that classes should be open for extension but closed for modification.
  • Code Duplication - The code for creating different document types would likely be duplicated in multiple places, leading to maintenance issues.

A Creation of Different Types of Documents System with Factory Pattern

A common real-world example of the Factory Design Pattern is the creation of different types of documents in a document processing application. Consider a scenario where you have a document editor application that can create different types of documents, such as Resume, Report, and Letter.

A diagram can help clarify the structure and interactions in the Factory Design Pattern. Here’s a visual representation of the Factory Pattern for creating different types of documents.

Factory Design Pattern

How It Works

  1. Client Code - Requests a document creation by using the factory interface (IDocumentFactory).

  2. Factory Interface -The client interacts with the factory interface, requesting a document.

  3. Concrete Factory - The specific factory (e.g., PdfDocumentFactory) creates and returns an instance of the corresponding document type (e.g., PdfDocument).

  4. Document Creation - The client interacts with the IDocument interface to use the document, without needing to know the details of the document's creation.

Example

Here’s the entire code example using the Factory Pattern in C#.

// Product interface
public interface IDocument
{
    void Create();
}

// Concrete Products
public class Resume : IDocument
{
    public void Create()
    {
        Console.WriteLine("Creating a Resume");
    }
}

public class Report : IDocument
{
    public void Create()
    {
        Console.WriteLine("Creating a Report");
    }
}

public class Letter : IDocument
{
    public void Create()
    {
        Console.WriteLine("Creating a Letter");
    }
}

// Factory interface
public interface IDocumentFactory
{
    IDocument CreateDocument();
}

// Concrete Factories
public class ResumeFactory : IDocumentFactory
{
    public IDocument CreateDocument()
    {
        return new Resume();
    }
}

public class ReportFactory : IDocumentFactory
{
    public IDocument CreateDocument()
    {
        return new Report();
    }
}

public class LetterFactory : IDocumentFactory
{
    public IDocument CreateDocument()
    {
        return new Letter();
    }
}

class Program
{
    static void Main()
    {
        // Client code using the Factory pattern
        IDocumentFactory resumeFactory = new ResumeFactory();
        IDocument resume = resumeFactory.CreateDocument();
        resume.Create(); // Output: Creating a Resume

        IDocumentFactory reportFactory = new ReportFactory();
        IDocument report = reportFactory.CreateDocument();
        report.Create(); // Output: Creating a Report

        IDocumentFactory letterFactory = new LetterFactory();
        IDocument letter = letterFactory.CreateDocument();
        letter.Create(); // Output: Creating a Letter
    }
}

Output

Factory Design Pattern

Advantages of the Factory Pattern in this Example.

  • Decoupling - The client code is decoupled from the specific implementations (Resume, Report, Letter). It only depends on the IDocumentFactory and IDocument interfaces.
  • Easy to Extend - If a new document type (e.g., Invoice) needs to be added, you can simply create a new InvoiceFactory and Invoice class without modifying any existing code.
  • Scalability - The system can easily scale with new types of documents without changing the core logic.

Real-World Example - Transport System

A transport booking system allows users to book various modes of transportation, such as Car, Bus, or Bicycle. Each type of transport has different characteristics and booking procedures, but the system should be able to handle them all through a unified interface. Using the Factory Pattern, the transport system can dynamically create and manage different vehicle objects.

Example

// Transport interface
public interface ITransport
{
    void Book();
}

// Concrete Transport Classes
public class Car : ITransport
{
    public void Book()
    {
        Console.WriteLine("Car has been booked.");
    }
}

public class Bus : ITransport
{
    public void Book()
    {
        Console.WriteLine("Bus has been booked.");
    }
}

public class Bicycle : ITransport
{
    public void Book()
    {
        Console.WriteLine("Bicycle has been booked.");
    }
}

// Factory interface
public interface ITransportFactory
{
    ITransport CreateTransport();
}

// Concrete Factories
public class CarFactory : ITransportFactory
{
    public ITransport CreateTransport()
    {
        return new Car();
    }
}

public class BusFactory : ITransportFactory
{
    public ITransport CreateTransport()
    {
        return new Bus();
    }
}

public class BicycleFactory : ITransportFactory
{
    public ITransport CreateTransport()
    {
        return new Bicycle();
    }
}

// Client code
class Program
{
    static void Main(string[] args)
    {
        // Simulating user input for transport selection
        string transportType = "Bus"; // Can be "Car", "Bus", or "Bicycle"
        ITransportFactory factory = GetTransportFactory(transportType);

        if (factory != null)
        {
            ITransport transport = factory.CreateTransport();
            transport.Book(); // Booking the transport
        }
        else
        {
            Console.WriteLine("Invalid transport type.");
        }
    }

    // Factory selection logic
    public static ITransportFactory GetTransportFactory(string transportType)
    {
        switch (transportType)
        {
            case "Car":
                return new CarFactory();
            case "Bus":
                return new BusFactory();
            case "Bicycle":
                return new BicycleFactory();
            default:
                return null;
        }
    }
}

Output

Factory Design Pattern

Advantages in a Real-World Scenario

  • Decoupling Creation Logic - The client code doesn’t need to know the specific details of how each transport type is created. It only interacts with the ITransportFactory and ITransport interfaces.
  • Extensibility - If new transport types (e.g., Train, Taxi, or Scooter) are introduced, you can add new factory and transport classes without changing the existing code.
  • Flexibility - Different transport types can be instantiated dynamically based on user input or other conditions (e.g., availability, pricing, etc.).
  • Maintenance - The code is easier to maintain because the transport creation logic is centralized in factories. Any change in the transport creation process is isolated from the rest of the system.
  • Reusability - The transport booking logic is reusable and can be extended to accommodate new features, such as pricing strategies, vehicle conditions, or booking rules.

Applications of the Factory Design Pattern

  • GUI Frameworks - Creating platform-specific components (Windows, macOS, Linux) through a factory.
  • Database Access - Switching between different databases (e.g., MySQL, SQL Server) based on configurations.
  • Logging Libraries - Creating different types of loggers (file logger, console logger, database logger) through a factory.
  • Game Development - Creating different types of game entities (monsters, players, NPCs) dynamically based on the game state.
  • Parser Tools - Dynamically creating different types of file parsers (e.g., XML, JSON, CSV) using a factory.

Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question