✨ Shield now has support for Avalonia UI

Abstract Factory Pattern in C#: Full Guide

Jun 18, 2023 | C#, .NET

You might be wondering, what’s up with all the buzz around abstract factory patterns in the C# realm? Is it really worth your time? The answer is an emphatic ‘Yes’. But why, you ask? Read on to find answers to all your questions surrounding this design pattern. From basic understanding, to implementation, to real-world examples, we’ve got it all covered!

Understanding the Concept of Abstract Factory Pattern in C#

Before starting a journey, it’s always prudent to know the ‘why’ and ‘what’ of the destination. Same applies for our abstract factory pattern journey. This section aims to get you familiar with the concept.

Definition of Abstract Factory Pattern

Let’s call the Abstract Factory Pattern a ‘super factory’. It’s a factory of factories, if you will. Technically, it’s a creational design pattern that provides an interface for creating families of related or dependent objects, without specifying their concrete classes.

Importance and Use of the Abstract Factory Pattern in C#

When you need to ensure that a class can only use products from a single family together, or when a family of related products is designed to work together, the abstract factory pattern becomes your ultimate lifesaver. It fits in perfectly while working with a large number of objects that need to be unified under a single theme. Stick with me to understand its potential.

The Abstract Factory Design Pattern in C#: An Overview

Now that you’re familiar with the ‘what’ and ‘why’ of the abstract factory pattern, let’s dive deeper into its ‘how’. Attaining that Sherlock-level understanding of its components can indeed feel like a mystery. But no worries, I’m Watson to your Sherlock, guiding you through every step!

Components of the Abstract Factory Design Pattern in C#

The Abstract Factory pattern has four main components:

  • Abstract Factory: Declares an interface for operations that create abstract objects.
  • Concrete Factory: Implements the operations to create concrete products.
  • Abstract Product: Declares an interface for a type of product object.
  • Concrete Product: Defines a product object to be created by the corresponding Concrete Factory.

Look at this piece of C# code, it’s as simple as PI (or Pie, if you’re not into Maths). And yes, here’s an unintentional joke before you dive into the code – Why do programmers always mix up Christmas and Halloween? Because Oct 31 == Dec 25!

//Abstract Product
public interface ICar
{
    string Name { get; }
}

//Concrete Product
public class Sedan : ICar
{
    public string Name => "Sedan";
}

//Concrete Product
public class SUV : ICar
{
    public string Name => "SUV";
}

//Abstract Factory
public interface ICarFactory
{
    ICar CreateCar();
}

//Concrete Factory
public class SedanFactory : ICarFactory
{
    public ICar CreateCar()
    {
        return new Sedan();
    }
}

//Concrete Factory
public class SUVFactory : ICarFactory
{
    public ICar CreateCar()
    {
        return new SUV();
    }
}

The Sudoku lovers amongst coders will love this one: much like Sudoku squares ensure consistency with the numbers, Abstract Factory pattern ensures consistency with objects!

C# Abstract Factory in Practice: A Basic Example

Now that you’re familiar with the components, let’s put them into practice. And yes, if you’re still wondering, cars are my favorite example while explaining abstract factories. Why cars you ask? Because, much like cars and their components, objects in code should work together seamlessly and “drive” the program towards its destination!

Let’s add an extra pinch of fun with a different well-known car theme but in a constructive way:

[...]

public class Client
{
    public Client(ICarFactory factory)
    {
        var car = factory.CreateCar();
        System.Console.WriteLine($"Created a {car.Name}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        new Client(new SedanFactory());
        new Client(new SUVFactory());

        System.Console.ReadKey();
    }
}

This looks simple, right? And Admit it, you’re secretly in love with the charm of the Abstract Factory pattern! Here, the Client class doesn’t need to know about the actual concrete classes.

The Difference Between Factory and Abstract Factory Design Pattern in C#

You might be thinking to yourself, “Hey, I’ve heard of the Factory Design Pattern for ‘Donkey’s years’ (yes, that’s British for ‘a long time’), so why should I bother with the Abstract Factory Pattern?” Well, let’s break it down for you.

Characteristics and Function of the Factory Design Pattern in C#

The Factory Design Pattern in C# is another creational design pattern, which provides an interface for creating objects, allowing subclasses to decide which class to instantiate. It’s there to abstract object creation, but it doesn’t enforce any constraint or requirement on the product families.

Features and Implementation of the Abstract Factory Design Pattern in C#

Enter the Abstract Factory pattern, Batman to Factory pattern’s Robin. It’s similar to the Factory pattern, but provides another level of abstraction, allowing you to create families of related objects without specific knowledge of their concrete classes.

Turn on the switch of curiosity and let’s dabble with some more code, shall we?

[...]

//Abstract Product
public interface IAutomobile
{
    string Name { get; }
}

//Concrete Product
public class Sedan : IAutomobile
{
    public string Name => "Sedan";
}

//Concrete Product
public class Hatchback : IAutomobile
{
    public string Name => "Hatchback";
}

//Abstract Factory
public interface IAutomobileFactory
{
    IAutomobile CreateAutomobile();

    //Additional function compared to the basic factory pattern to support families of products
    IAutomobile CreateSportsVersion();
}

//Concrete Factory
public class SedanFactory : IAutomobileFactory
{
    public IAutomobile CreateAutomobile()
    {
        return new Sedan();
    }

    public IAutomobile CreateSportsVersion()
    {
        return new SportsSedan();
    }
}

[...]

We’ve added a CreateSportsVersion method to support the creation of a family of Sedan products. What’s more harmonious than a family working together?

A Closer Look at the Abstract Factory Pattern .NET

Here’s some food for thought: How does all this tie in with the .NET framework? Will this seamless harmony resonate there too? The answer is a thumping ‘Yes’, so don’t blink or you’ll miss out!

Understanding the use of Abstract Factory Pattern in .NET

.NET extensively uses the Abstract Factory pattern especially in settings where the system needs to be independent of how its objects are created, composed, and represented. We’ve been exploring the car theme so far. However, in .NET, the Abstract Factory pattern isn’t just confined to a parking lot of automobiles!

Case Study: Abstract Factory Pattern .NET in Real-life Coding Problem

The System.Data.Common namespace in .NET is a perfect example of the Abstract Factory pattern. It provides a way for the user to create instances of classes that provide access to the underlying data source. These classes include DbConnection, DbCommand, and DbDataAdapter objects. Just like how the Abstract Factory pattern works, the user doesn’t need to know about the actual database or data source, as long as it’s compliant with the factories used.

Are you starting to see the beauty of the Abstract Factory pattern? And yes, I agree, data connectivity in .NET is indeed a breathtaking dance of objects, brought out magnificently by the Abstract Factory!

Step-by-Step: Implementing the Abstract Factory Pattern C#

Let’s now get our hands dirty, the coder’s favorite part! Let’s create our very own abstract factory, a beautiful masterpiece of code. Ready?

Setting up the C# Abstract Factory Pattern

There’s an old saying that goes “Set up right for an overnight success”. So, let’s start by setting up our C# abstract factory before we use it to solve the real-world farming problem (car fans don’t fret, thinking of trying out a different theme to show the versatility! ).

// Abstract Product A
public interface IPlant
{
    string Grow();
}

// Concrete Product A1
public class Potato : IPlant
{
    public string Grow()
    {
        return "Growing a potato.";
    }
}

// Concrete Product A2
public class Tomato : IPlant
{
    public string Grow()
    {
        return "Growing a tomato.";
    }
}

// Abstract Product B
public interface IAnimal
{
    string Feed();
}

// Concrete Product B1
public class Cow : IAnimal
{
    public string Feed()
    {
        return "Feeding a cow.";
    }
}

// Concrete Product B2
public class Chicken : IAnimal
{
    public string Feed()
    {
        return "Feeding a chicken.";
    }
}

// Abstract Factory
public interface IFarmFactory
{
    IPlant CreatePlant();
    IAnimal CreateAnimal();
}

// Concrete Factory 1
public class VegetableFarm : IFarmFactory
{
    public IPlant CreatePlant()
    {
        return new Potato();
    }

    public IAnimal CreateAnimal()
    {
        return new Cow();
    }
}

// Concrete Factory 2
public class PoultryFarm : IFarmFactory
{
    public IPlant CreatePlant()
    {
        return new Tomato();
    }

    public IAnimal CreateAnimal()
    {
        return new Chicken();
    }
}

Here, we have started by defining our abstract products, concrete products, abstract factories, and concrete factories. The use case is simple: we have a plant and an animal for each farm.

Abstract Factory in C#: Code Example

Here comes the part everyone’s been waiting for. Don’t worry! You’ve got this. Just like how Javascript and Java are as connected as Car and Carpet. Right? We have set up our factories above, let’s put them to use.

[...]

public class Farmer
{
    public Farmer(IFarmFactory factory)
    {
        var plant = factory.CreatePlant();
        System.Console.WriteLine(plant.Grow());

        var animal = factory.CreateAnimal();
        System.Console.WriteLine(animal.Feed());
    }
}

class Program
{
    static void Main(string[] args)
    {
        new Farmer(new VegetableFarm());

        System.Console.WriteLine();

        new Farmer(new PoultryFarm());

        System.Console.ReadKey();
    }
}

Exciting, right? This example above shows two different types of farms in action using the Abstract Factory pattern. As you can see, all the farmer cares about is that he works on a farm, not what type of farm he’s dealing with. That’s our lovely Abstract Factory’s doing!

C# Abstract Factory Pattern: Deep Dive into a Real-World Example

Enough gazing at the clouds above, let’s return to reality. You might be asking yourself, ‘Does it even benefit real-world software applications?’ The answer is, ‘Where have you been? We’ve been talking about its real-world applications all along!’

Application of C# Abstract Factory Design Pattern in Software Development

Suffice to say, in software development, Abstract Factory shines in scenarios where the system should be independent of how external APIs or peripheral systems are organized, or upon changes in them. Remember the System.Data.Common namespace case I outlined earlier? That’s gold, right there!

Real-world Example of Abstract Factory Design Pattern: A Practical Application

Let’s talk about UI widgets in different operating systems. The ‘look and feel’ can be abstracted into a WidgetFactory interface. Concrete subclasses like WindowsWidgetFactory and MacWidgetFactory can provide the apt look and feel under different operating systems. Notice how beautifully the Abstract Factory slides in?

In Summary: The Essence of the Abstract Design Pattern in C#

Congratulations, you’ve weathered the storm! Now, let’s consolidate before popping the champagne to celebrate your newfound expertise!

Recap: Benefits and Challenges of Using Abstract Factory Design Pattern C#

The Abstract factory pattern shines in providing a way to encapsulate a group of individual factories that have a common theme, without specifying concrete classes. However, adding new kinds of products can be challenging as the abstract factory interface must change which can affect all subclasses.

Final Words on the Abstract Factory C# Example Explained

Wrap-up: The Abstract Factory pattern provides a high level of flexibility when dealing with related, dependent, or engaging families of objects. Heard about the famous SOLID principle of software design? This is a perfect design pattern for driving towards ‘D’ – the Dependency Inversion principle!

Extended Learning: Other Resources for the Abstract Factory Design Pattern

Congratulations on your triumphant trip through the exhilarating world of the Abstract Factory pattern. But the journey doesn’t stop here!

Recommended Books and Online Resources on Abstract Factory Design Pattern

Look for ‘Design Patterns: Elements of Reusable Object-Oriented Software’ by the Gang of Four, and you’ll never regret it. Also, ‘Head First Design Patterns’ is another gem.

Understanding Abstract Pattern C# and Related Design Patterns

Patterns are everywhere from maths to music to coding! Keep exploring patterns like Singleton, Factory, Builder, Prototype, and more. They are a supernova of elegant solutions to common coding problems. Sky’s the limit! Speaking of patterns, patterns in a Disco ball are too intense, right? Well, that’s how magical and intense learning about design patterns can be!

Remember, the only thing that differentiates you from being an average coder to being a supercoder is your knowledge of design patterns! So, what’s now? Are you ready to take action and implement this pattern in your next C# project? Remember, action is a basic necessity like breathing, sleeping, and debugging. Get set, code!

You May Also Like