02 Dec 2023



Advanced

Real-world examples of where the factory design pattern might be used:

  1. Database Connection: Imagine a scenario where your application needs to connect to different types of databases, such as MySQL, PostgreSQL, or MongoDB. Instead of having a single class handling all the different types of database connections, you can use a database connection factory. This factory would have methods to create instances of different database connection classes based on the type of database needed.
// Product
public interface IDatabaseConnection
{
    void Connect();
}

// Concrete Products
public class MySqlConnection : IDatabaseConnection { /* Implementation for MySQL connection */ }
public class PgSqlConnection : IDatabaseConnection { /* Implementation for PostgreSQL connection */ }
public class MongoDbConnection : IDatabaseConnection { /* Implementation for MongoDB connection */ }

// Factory
public interface IDatabaseConnectionFactory
{
    IDatabaseConnection CreateConnection(string databaseType);
}

// Concrete Factory
public class DatabaseConnectionFactory : IDatabaseConnectionFactory
{
    public IDatabaseConnection CreateConnection(string databaseType)
    {
        switch (databaseType)
        {
            case "MySQL":
                return new MySqlConnection();
            case "PostgreSQL":
                return new PgSqlConnection();
            case "MongoDB":
                return new MongoDbConnection();
            default:
                throw new ArgumentException("Invalid database type");
        }
    }
}

// Client Code
class DatabaseClient
{
    static void Main()
    {
        IDatabaseConnectionFactory factory = new DatabaseConnectionFactory();

        // Client code requesting a MySQL connection
        IDatabaseConnection mySqlConnection = factory.CreateConnection("MySQL");
        mySqlConnection.Connect();

        // Client code requesting a MongoDB connection
        IDatabaseConnection mongoDbConnection = factory.CreateConnection("MongoDB");
        mongoDbConnection.Connect();
    }
}


  1. Logger Creation: Logging is an essential part of software development, and different systems might require different logging mechanisms. A logging factory can create instances of loggers based on the logging requirements. For example, you might have different loggers for console logging, file logging, or network logging.
// Product
public interface ILogger
{
    void Log(string message);
}

// Concrete Products
public class ConsoleLogger : ILogger { /* Implementation for console logging */ }
public class FileLogger : ILogger { /* Implementation for file logging */ }
public class NetworkLogger : ILogger { /* Implementation for network logging */ }

// Factory
public interface ILoggerFactory
{
    ILogger CreateLogger(string loggerType);
}

// Concrete Factory
public class LoggerFactory : ILoggerFactory
{
    public ILogger CreateLogger(string loggerType)
    {
        switch (loggerType)
        {
            case "Console":
                return new ConsoleLogger();
            case "File":
                return new FileLogger();
            case "Network":
                return new NetworkLogger();
            default:
                throw new ArgumentException("Invalid logger type");
        }
    }
}

// Client Code
class LoggerClient
{
    static void Main()
    {
        ILoggerFactory factory = new LoggerFactory();

        // Client code requesting a console logger
        ILogger consoleLogger = factory.CreateLogger("Console");
        consoleLogger.Log("Log message to console");

        // Client code requesting a file logger
        ILogger fileLogger = factory.CreateLogger("File");
        fileLogger.Log("Log message to file");
    }
}

  1. UI Component Creation: Consider a scenario where you are developing a graphical user interface (GUI) library. You might have different types of UI components, such as buttons, text fields, and checkboxes. A UI component factory could create instances of these components based on the specific requirements of the application using the library.
// Product
public interface IUIComponent
{
    void Render();
}

// Concrete Products
public class Button : IUIComponent { /* Implementation for button */ }
public class TextField : IUIComponent { /* Implementation for text field */ }
public class CheckBox : IUIComponent { /* Implementation for checkbox */ }

// Factory
public interface IUIComponentFactory
{
    IUIComponent CreateUIComponent(string componentType);
}

// Concrete Factory
public class UIComponentFactory : IUIComponentFactory
{
    public IUIComponent CreateUIComponent(string componentType)
    {
        switch (componentType)
        {
            case "Button":
                return new Button();
            case "TextField":
                return new TextField();
            case "CheckBox":
                return new CheckBox();
            default:
                throw new ArgumentException("Invalid UI component type");
        }
    }
}

// Client Code
class UIClient
{
    static void Main()
    {
        IUIComponentFactory factory = new UIComponentFactory();

        // Client code requesting a button
        IUIComponent button = factory.CreateUIComponent("Button");
        button.Render();

        // Client code requesting a text field
        IUIComponent textField = factory.CreateUIComponent("TextField");
        textField.Render();
    }
}

  1. Document Generation: In document processing applications, you might need to generate different types of documents, such as PDFs, Word documents, or HTML files. A document generation factory could create instances of document generation classes based on the desired output format.
// Product
public interface IDocumentGenerator
{
    void Generate();
}

// Concrete Products
public class PdfDocumentGenerator : IDocumentGenerator { /* Implementation for PDF generation */ }
public class WordDocumentGenerator : IDocumentGenerator { /* Implementation for Word generation */ }
public class HtmlDocumentGenerator : IDocumentGenerator { /* Implementation for HTML generation */ }

// Factory
public interface IDocumentGeneratorFactory
{
    IDocumentGenerator CreateDocumentGenerator(string format);
}

// Concrete Factory
public class DocumentGeneratorFactory : IDocumentGeneratorFactory
{
    public IDocumentGenerator CreateDocumentGenerator(string format)
    {
        switch (format)
        {
            case "PDF":
                return new PdfDocumentGenerator();
            case "Word":
                return new WordDocumentGenerator();
            case "HTML":
                return new HtmlDocumentGenerator();
            default:
                throw new ArgumentException("Invalid document format");
        }
    }
}
// Client Code
class DocumentClient
{
    static void Main()
    {
        IDocumentGeneratorFactory factory = new DocumentGeneratorFactory();

        // Client code requesting a PDF document generator
        IDocumentGenerator pdfGenerator = factory.CreateDocumentGenerator("PDF");
        pdfGenerator.Generate();

        // Client code requesting an HTML document generator
        IDocumentGenerator htmlGenerator = factory.CreateDocumentGenerator("HTML");
        htmlGenerator.Generate();
    }
}

  1. Vehicle Manufacturing: In the context of manufacturing, a vehicle assembly line could use the factory pattern. The assembly line might produce different types of vehicles like cars, trucks, or motorcycles. A vehicle factory would create instances of these vehicles based on the specifications provided.
// Product
public interface IVehicle
{
    void Manufacture();
}

// Concrete Products
public class Car : IVehicle { /* Implementation for car manufacturing */ }
public class Truck : IVehicle { /* Implementation for truck manufacturing */ }
public class Motorcycle : IVehicle { /* Implementation for motorcycle manufacturing */ }

// Factory
public interface IVehicleFactory
{
    IVehicle CreateVehicle(string vehicleType);
}

// Concrete Factory
public class VehicleFactory : IVehicleFactory
{
    public IVehicle CreateVehicle(string vehicleType)
    {
        switch (vehicleType)
        {
            case "Car":
                return new Car();
            case "Truck":
                return new Truck();
            case "Motorcycle":
                return new Motorcycle();
            default:
                throw new ArgumentException("Invalid vehicle type");
        }
    }
}
// Client Code
class VehicleClient
{
    static void Main()
    {
        IVehicleFactory factory = new VehicleFactory();

        // Client code requesting a car
        IVehicle car = factory.CreateVehicle("Car");
        car.Manufacture();

        // Client code requesting a motorcycle
        IVehicle motorcycle = factory.CreateVehicle("Motorcycle");
        motorcycle.Manufacture();
    }
}


  1. Payment Gateway Integration: When integrating with various payment gateways, each gateway might have its own implementation details. A payment gateway factory could create instances of payment gateway classes based on the selected payment method.
// Product
public interface IPaymentGateway
{
    void ProcessPayment();
}

// Concrete Products
public class PayPalGateway : IPaymentGateway { /* Implementation for PayPal payment processing */ }
public class StripeGateway : IPaymentGateway { /* Implementation for Stripe payment processing */ }
public class SquareGateway : IPaymentGateway { /* Implementation for Square payment processing */ }

// Factory
public interface IPaymentGatewayFactory
{
    IPaymentGateway CreatePaymentGateway(string gatewayType);
}

// Concrete Factory
public class PaymentGatewayFactory : IPaymentGatewayFactory
{
    public IPaymentGateway CreatePaymentGateway(string gatewayType)
    {
        switch (gatewayType)
        {
            case "PayPal":
                return new PayPalGateway();
            case "Stripe":
                return new StripeGateway();
            case "Square":
                return new SquareGateway();
            default:
                throw new ArgumentException("Invalid payment gateway type");
        }
    }
}
// Client Code
class PaymentClient
{
    static void Main()
    {
        IPaymentGatewayFactory factory = new PaymentGatewayFactory();

        // Client code requesting a PayPal payment gateway
        IPaymentGateway paypalGateway = factory.CreatePaymentGateway("PayPal");
        paypalGateway.ProcessPayment();

        // Client code requesting a Stripe payment gateway
        IPaymentGateway stripeGateway = factory.CreatePaymentGateway("Stripe");
        stripeGateway.ProcessPayment();
    }
}

Note📝: Above pseudo-code snippets illustrate the Factory Design Pattern. In a real-world scenario, you would likely have more sophisticated implementations and considerations.

In each of these examples, the factory pattern helps encapsulate the object creation logic, making the system more modular and adaptable to changes. It allows for easy extension by adding new classes or types without modifying the existing code, adhering to the open/closed principle of object-oriented design.

software-design-patterns
factory-design-pattern
real-world-examples
c#