Abstract Factory Design Pattern

The Abstract Factory is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern ensures that objects created by a factory belong to a consistent family, promoting flexibility and scalability in the codebase.

When to Use the Abstract Factory Pattern?

  1. When your system needs to work with multiple families of related objects.
  2. When ensuring that related objects are used together is a priority.
  3. When you want to abstract the instantiation process from the client code.

Key Features of the Abstract Factory Pattern

  1. Family of Products: Supports the creation of families of related or dependent objects.
  2. Abstraction: Separates the client code from the actual creation process.
  3. Consistency: Ensures that products from the same family work well together.
  4. Encapsulation: Hides the details of the object creation from the client code.

What are the Pros and Cons?

Pros

  • Flexibility: Adding new families of products requires minimal changes to the client code.
  • Decoupling: Promotes loose coupling by separating the client code from the concrete implementations.
  • Consistency: Ensures that only compatible products are used together.

Cons

  • Complexity: Can introduce multiple classes and interfaces, increasing complexity.
  • Extensibility Challenges: Adding new product types to existing families may require changes to all factory interfaces.

Example: Theme Park

Consider a theme park that offers experiences in two styles: Futuristic and Medieval. Each style includes a consistent set of items such as costumes, rides, and menus. The Abstract Factory pattern acts as the system ensuring that all items in a visitor’s experience belong to the same theme. For example, selecting the Futuristic theme provides a spacesuit costume, a spaceship ride, and a tech-inspired menu, while the Medieval theme offers knight’s armor, a horse ride, and a rustic feast.

Class Diagram

Implementation in C#

Let’s see how we can use the Abstract Factory design pattern in practice. Consider the theme park scenario

				
					/// <summary>
/// Abstract Product - Ride
/// </summary>
public interface ICostume
{
    void Wear();
}

/// <summary>
/// Abstract Product - Costume
/// </summary>
public interface IRide
{
    void Experience();
}

/// <summary>
/// Concrete Product - Futuristic Costume
/// </summary>
public class FuturisticCostume : ICostume
{
    public void Wear()
    {
        Console.WriteLine("Wearing a spacesuit.");
    }
}

/// <summary>
/// Concrete Product - Medieval Costume
/// </summary>
public class MedievalCostume : ICostume
{
    public void Wear()
    {
        Console.WriteLine("Wearing a knight's armor.");
    }
}

/// <summary>
/// Concrete Product - Futuristic Ride
/// </summary>
public class FuturisticRide : IRide
{
    public void Experience()
    {
        Console.WriteLine("Riding a spaceship.");
    }
}

/// <summary>
/// Concrete Product - Medieval Ride
/// </summary>
public class MedievalRide : IRide
{
    public void Experience()
    {
        Console.WriteLine("Riding a horse.");
    }
}

/// <summary>
/// Abstract Factory
/// </summary>
public interface IThemeParkFactory
{
    ICostume CreateCostume();
    IRide CreateRide();
}

/// <summary>
/// Concrete Factory - Futuristic Theme
/// </summary>
public class FuturisticThemeParkFactory : IThemeParkFactory
{
    public ICostume CreateCostume()
    {
        return new FuturisticCostume();
    }

    public IRide CreateRide()
    {
        return new FuturisticRide();
    }
}

/// <summary>
/// Concrete Factory - Medieval Theme
/// </summary>
public class MedievalThemeParkFactory : IThemeParkFactory
{
    public ICostume CreateCostume()
    {
        return new MedievalCostume();
    }

    public IRide CreateRide()
    {
        return new MedievalRide();
    }
}

/// <summary>
/// Client Code
/// </summary>
public class ThemePark
{
    private readonly ICostume _costume;
    private readonly IRide _ride;

    public ThemePark(IThemeParkFactory factory)
    {
        _costume = factory.CreateCostume();
        _ride = factory.CreateRide();
    }

    public void EnjoyExperience()
    {
        _costume.Wear();
        _ride.Experience();
    }
}

// Main Program
class Program
{
    static void Main(string[] args)
    {
        // Futuristic Theme
        IThemeParkFactory futuristicFactory = new FuturisticThemeParkFactory();
        ThemePark futuristicPark = new ThemePark(futuristicFactory);
        Console.WriteLine("Futuristic Theme Park Experience:");
        futuristicPark.EnjoyExperience();

        Console.WriteLine();

        // Medieval Theme
        IThemeParkFactory medievalFactory = new MedievalThemeParkFactory();
        ThemePark medievalPark = new ThemePark(medievalFactory);
        Console.WriteLine("Medieval Theme Park Experience:");
        medievalPark.EnjoyExperience();
    }
}
				
			

Here is the output from the application

				
					Futuristic Theme Park Experience:
Wearing a spacesuit.
Riding a spaceship.

Medieval Theme Park Experience:
Wearing a knight's armor.
Riding a horse.
				
			

Explanation of the Code

  1. Abstract Products: ICostume and IRide define the interfaces for costumes and rides.
  2. Concrete Products: FuturisticCostume, MedievalCostume, FuturisticRide, and MedievalRide implement the respective interfaces.
  3. Abstract Factory: IThemeParkFactory defines methods to create costumes and rides.
  4. Concrete Factories: FuturisticThemeParkFactory and MedievalThemeParkFactory implement the abstract factory to create themed products.
  5. Client Code: The ThemePark class uses the factory to create and use products without relying on their concrete implementations.

Summary

The Abstract Factory design pattern is an excellent choice when your system requires families of related objects to be used together consistently. While it introduces some complexity, the benefits of decoupling, consistency, and scalability make it an essential pattern for building flexible and maintainable software systems.

January 5, 2025
Builder Design Pattern
Scroll to top