Why we need Abstract Factory Design Pattern ?

If you like this article. Kindly comment. So, it motivates me to write more articles.

Category: Abstract factory design patterns come under the category of creational design patterns.

Why do we need creational patterns?

They are used to separate & encapsulate object creation logic from client code requesting objects.

Why do we need an Abstract Factory Design Pattern?

Due to the limitation of the "Factory Method Design Pattern" mentioned below.

The factory method isn't designed to create multiple related objects. In it, one factory is made for creating & returning one object.

If you want to create a different object, then you have to create another factory method for it.

So, in this case, you can use the "Abstract Factory" Design Pattern.

Components of Abstract Factory

Let us take an example of a UI Component library for different operating systems like Windows, Mac, and Linux.

We want our library to create objects like TextBox, Button, and Dropdown, with a unique theme for each operating system.

So our Factory class is capable of creating TextBox, Button, etc.

Abstract Product

public abstract Button
{
    public string ButtonName get; set;

    public abstract void Render (string btnName);
}
public abstract TextBox
{
    public string Placeholder get; set;

    public abstract void Render (string placeholder);
}

Concrete Product: for Windows operating system.

public class WindowButton: Button
{
    public override void Render (string btnName)
    {
        this.ButtonName = btnName;
        Console.WriteLine("In window OS, Button Rendered with button Name :" + ButtonName);
    }
}
public class WindowTextBox: TextBox
{
    public override void Render (string placeHolder)
    {
        this.Placeholder = placeHolder;
        Console.WriteLine("In window OS, TextBox Rendered with Placeholder :" + PlaceHolder);
    }
}

Concrete Product: for Mac operating system.

public class MacButton: Button
{
    public override void Render (string btnName)
    {
        this.ButtonName = btnName;
        Console.WriteLine("Mac Button Rendered " + ButtonName);
    }
}
public class MacTextBox: TextBox
{
    public override void Render (string placeholder)
    {
        this.Placeholder = placeholder;
        Console.WriteLine("Mac TextBox Rendered " + Placeholder);
    }
}

Abstract UI Factory: Hence, we use abstract class, not interface, to provide a common theme when needed.

public abstract class UIFactory
{
    public abstract TextBox CreateTextBox(string placeholder);
    public abstract Button CreateButton(string buttonName);
}

Concrete: Window UI Factory.

public class WindowUIFactory: UIFactory
{
    public override TextBox CreateTextBox(string placeholder)
    {
        return new WindowTextBox(placeholder);
    }
    public override Button CreateButton(string buttonName)
    {
        return new WindowButton(buttonName);
    }
}

Concrete: Mac UI Factory.

public class MacUIFactory: UIFactory
{
    public override TextBox CreateTextBox(string placeholder)
    {
        return new MacTextBox(placeholder);
    }
    public override Button CreateButton(string buttonName)
    {
        return new MacButton(buttonName);
    }
}

Client Class

public class Program
{
    UIFactory winFactory = new WindowUIFactory();

    TextBox txtBox = winFactory.CreateTextBox("Enter Name");
    txtBox.Render();

    Button btn = winFactory.CreateButton("Submit");
    btn.Render();
}

Output 

In window OS, TextBox Rendered With Placeholder : Enter Name

In window OS, Button Rendered with Button Name : Submit


Similar Articles