Design Patterns

Last Updated: 9/7/2024

Abstract Factory

  • Provides an interface for creating a families of related objects
  • Factory method is a method
  • Abstract Factory is an abstraction (interface)

Classical Structure

Abstract Classical Structure

Scenario

  • Build a GUI framework. In framework we have controls like button, textbox, dropdown. Support themes like Material, Ant.
  • Based on theme selected, the controls should have consistent look and feel.

Problem

  • Violates Open Closed Principle. If you need support another theme, you need to add another if condition
public interface IWidget
{
    void Render();
}
public interface IButton: IWidget {}
public interface ITextbox: IWidget {}

public class MaterialButton: IButton
{
    public void Render()
    {
        Console.WriteLine("Material Button");
    }
}
public class MaterialTextbox : ITextbox
{
    public void Render()
    {
        Console.WriteLine("Material Textbox");
    }
}

public class AntButton : IButton
{
    public void Render()
    {
        Console.WriteLine("Ant Button");
    }
}
public class AntTextbox: ITextbox
{
    public void Render()
    {
        Console.WriteLine("Ant Textbox");
    }
}

public enum Theme
{
    Material,
    Ant
}

public class ContactForm
{
    public void Render(Theme theme) 
    {
        if (theme == Theme.Material)
        {
            new MaterialTextbox().Render();
            new MaterialButton().Render();
        }
        else if (theme == Theme.Ant)
        {
            new AntTextbox().Render();
            new AntButton().Render();
        }
    }
}

Solution

public interface IWidgetFactory
{
    IButton CreateButton();
    ITextbox CreateTextbox();
}

public class MaterialWidgetFactory : IWidgetFactory
{
    public IButton CreateButton()
    {
        return new MaterialButton();
    }

    public ITextbox CreateTextbox()
    {
        return new MaterialTextbox();
    }
}
public class AntWidgetFactory : IWidgetFactory
{
    public IButton CreateButton()
    {
        return new AntButton();
    }

    public ITextbox CreateTextbox()
    {
        return new AntTextbox();
    }
}

public class ContactForm
{
    public void Render(IWidgetFactory widgetFactory) 
    {
        widgetFactory.CreateTextbox().Render();
        widgetFactory.CreateButton().Render();
    }
}

new ContactForm().Render(new MaterialWidgetFactory());

Example Structure

Abstract Example Structure

Example Code