Master Factory Method Design Pattern in C#: Step-by-Step Guide with 2 Examples

Introduction

The Factory Method Design Pattern is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. In C#, this pattern is widely used to promote flexibility in object creation and decouple the client code from the actual implementation of the objects.

Factory Method Design Pattern
Factory Method Design Pattern

Intent

The intent of the Factory Method Design Pattern is to define an interface for creating objects in a superclass, while allowing subclasses to modify the type of objects created. It aims to provide a flexible way to create objects without directly specifying their classes in the client code.

Problem

In software development, there are situations where the exact class of objects to be created is not known at compile time or needs to be determined dynamically. Directly instantiating objects using constructors in the client code can lead to tight coupling and make the code less flexible and scalable.

Solution

The Factory Method Design Pattern addresses this problem by introducing a factory method in a superclass or interface. This method is responsible for creating objects of a specific type, but the actual class of the object is determined by subclasses. This way, the client code can use the factory method to create objects without knowing their exact types.

Real-World Analogy

Think of a manufacturing plant that produces different types of vehicles. The plant follows a standard process for assembling vehicles but can produce cars, trucks, or motorcycles based on customer requirements. The assembly line represents the factory method, and each vehicle type corresponds to a subclass that implements the factory method to create specific objects.

Structure

The Factory Method Design Pattern consists of several key components:

  1. Creator: Declares the factory method, which returns an object of a product type. It can be an abstract class or interface.
  2. ConcreteCreator: Implements the factory method to create objects of a specific product type.
  3. Product: Represents the object being created. It can be an abstract class or interface.
  4. ConcreteProduct: Implements the product interface to provide specific functionality.

Applicability

Use the Factory Method Design Pattern in C# when:

  • The exact class of objects to be created is not known at compile time.
  • Objects need to be created dynamically based on certain conditions or configurations.
  • You want to promote flexibility and decouple client code from object creation logic.
  • Different subclasses need to create objects of varying types within a common framework.

How to Implement: Factory Method Design Pattern

Here’s a step-by-step guide to implementing the Factory Method Design Pattern in C#:

  1. Define the Product Interface: Create an interface or abstract class to define the common functionality of objects to be created.
  2. Implement Concrete Products: Create concrete classes that implement the product interface to provide specific functionality.
  3. Declare the Factory Method: Define a factory method in a creator class (abstract or concrete) that returns objects of the product type.
  4. Implement Concrete Creators: Create concrete creator classes that implement the factory method to create specific types of products.
  5. Client Code: Use the factory method through the creator class to create objects without knowing their exact types.

Pros and Cons

Pros:

  • Flexibility: Allows for dynamic object creation based on runtime conditions.
  • Decoupling: Separates object creation logic from client code, promoting maintainability.
  • Scalability: Easily extendable to add new product types without modifying existing code.
  • Reuse: Encourages code reuse by standardizing object creation in a common framework.

Cons:

  • Complexity: Introduces additional classes and interfaces, which can increase complexity for small-scale applications.
  • Abstraction Overhead: Requires understanding of abstract classes and interfaces, which may add overhead for developers new to design patterns.
Here you can checkout our post on Builder Design Pattern in C#: Step-by-Step Guide with 3 Examples

Relations with Other Patterns

  • Abstract Factory: The Factory Method pattern focuses on creating individual objects, while the Abstract Factory pattern deals with creating families of related or dependent objects.
  • Singleton: The Factory Method pattern can be combined with the Singleton pattern to ensure that a single instance of a factory is used throughout the application.

Code Example 1

Let’s illustrate the Factory Method Pattern with a simplified example in C#:

// Product Interface
public interface IProduct
{
    void Operation();
}

// Concrete Products
public class ConcreteProductA : IProduct
{
    public void Operation()
    {
        Console.WriteLine("ConcreteProductA operation");
    }
}

public class ConcreteProductB : IProduct
{
    public void Operation()
    {
        Console.WriteLine("ConcreteProductB operation");
    }
}

// Creator (Abstract Factory)
public abstract class Creator
{
    public abstract IProduct FactoryMethod();
}

// Concrete Creators
public class ConcreteCreatorA : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProductA();
    }
}

public class ConcreteCreatorB : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProductB();
    }
}

// Client Code
class Program
{
    static void Main(string[] args)
    {
        Creator creatorA = new ConcreteCreatorA();
        IProduct productA = creatorA.FactoryMethod();
        productA.Operation();

        Creator creatorB = new ConcreteCreatorB();
        IProduct productB = creatorB.FactoryMethod();
        productB.Operation();
    }
}

In this example, we have a product interface (IProduct) and two concrete product classes (ConcreteProductA and ConcreteProductB). We also have an abstract creator class (Creator) with factory methods implemented in concrete creator classes (ConcreteCreatorA and ConcreteCreatorB). The client code creates products using the factory methods without knowing the exact product types.

Code Example 2

Let’s explore a real-life example of the Factory Method Pattern in C# using a scenario of a software company that develops different types of software products.

Real-Life Example: Software Product Development

Step 1: Define the Product Interface

First, we define an interface ISoftwareProduct that represents the common functionality of software products.

public interface ISoftwareProduct
{
    void Develop();
}

Step 2: Implement Concrete Products

Next, we create concrete classes that implement the ISoftwareProduct interface to represent different types of software products.

public class WebApplication : ISoftwareProduct
{
    public void Develop()
    {
        Console.WriteLine("Developing a web application...");
    }
}

public class MobileApp : ISoftwareProduct
{
    public void Develop()
    {
        Console.WriteLine("Developing a mobile app...");
    }
}

public class DesktopSoftware : ISoftwareProduct
{
    public void Develop()
    {
        Console.WriteLine("Developing desktop software...");
    }
}

Step 3: Declare the Factory Method

We define an abstract creator class SoftwareCompany with a factory method CreateProduct() that returns an ISoftwareProduct object.

public abstract class SoftwareCompany
{
    public abstract ISoftwareProduct CreateProduct();
}

Step 4: Implement Concrete Creators

Subclasses of SoftwareCompany implement the factory method to create specific types of software products.

public class WebApplicationCompany : SoftwareCompany
{
    public override ISoftwareProduct CreateProduct()
    {
        return new WebApplication();
    }
}

public class MobileAppCompany : SoftwareCompany
{
    public override ISoftwareProduct CreateProduct()
    {
        return new MobileApp();
    }
}

public class DesktopSoftwareCompany : SoftwareCompany
{
    public override ISoftwareProduct CreateProduct()
    {
        return new DesktopSoftware();
    }
}

Step 5: Client Code

Finally, we use the factory method through the concrete creator classes to create software products without knowing their exact types.

class Program
{
    static void Main(string[] args)
    {
        SoftwareCompany company1 = new WebApplicationCompany();
        ISoftwareProduct product1 = company1.CreateProduct();
        product1.Develop(); // Output: Developing a web application...

        SoftwareCompany company2 = new MobileAppCompany();
        ISoftwareProduct product2 = company2.CreateProduct();
        product2.Develop(); // Output: Developing a mobile app...

        SoftwareCompany company3 = new DesktopSoftwareCompany();
        ISoftwareProduct product3 = company3.CreateProduct();
        product3.Develop(); // Output: Developing desktop software...
    }
}

In this example, the SoftwareCompany acts as the creator with factory methods implemented in subclasses (WebApplicationCompany, MobileAppCompany, DesktopSoftwareCompany) to create specific types of software products (WebApplication, MobileApp, DesktopSoftware). The client code creates software products using the factory methods without directly instantiating concrete product classes, promoting flexibility and scalability in software development.

Conclusion

The Factory Method Design Pattern in C# provides a flexible and scalable approach to object creation by decoupling client code from the implementation of objects. By defining a factory method in a superclass and allowing subclasses to create specific types of objects, this pattern promotes code reuse, maintainability, and extensibility. Understanding and applying the Factory Method Pattern can significantly improve software design and development practices.

References

For more information and detailed references on the topics discussed in this article, please refer to the following link:

Leave a Comment

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

Scroll to Top