DEV Community

Abhinav Jha for The Polyglot Academy

Posted on

P3: Programming Design Patterns

Abstract Factory

Book Definition: The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

My Definition: Abstract factory pattern allows clients(in our case NYStylePizzaFactory) to use an abstract interface to create a set of relative(similar) products(like NYStyleCheesePizza) without actually knowing actual products that are actually produced.

Problem

I have a successful Pizza Stores so far but, I received some complaints on the quality of pizza produced by NYStylePizzaFactory. After investigating this issue, I found they are using low-quality ingredients for preparing pizza which they acquire from the local market place. This problem leads me to a situation where I need to find a solution to monitor and maintain my quality of ingredients that my franchises use for creating pizzas. So I read my Design Pattern Bible Head First Design Pattern.

So I found my solution with Abstract Factory Pattern this helped me to create an Ingredients Factory that will provide the ingredients for NYStylePizzaFactory and ChicagoStylePizzaFactory. Which I have implemented later in this article.

Solution

That's fairly complicated class diagram to draw; let's look at it all in terms of our PizzaStore:
Abstract Factory Method

What I have done?

Pizza Store UML

Code Implementation

I have not changed a lot in code for implementing abstract factory. Lets follow few steps to implement new changes.

Step 1: Create Ingredients factory to create pizza ingredients.

// filePath : Factory\IIngredientsFactory.cs
public interface IIngredientsFactory
{
    Dough CreateDough();
    Sauce CreateSauce();
    Cheese CreateCheese();
    Veggies[] CreateVeggies();
    Pepperoni CreatePepperoni();
    Clams CreateClam();
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Implement IIngredientsFactory and create NYPizzaIngredientFactory and ChicagoPizzaIngredientsFactory for supplying ingredients.

// filePath : Factory\NYPizzaIngredientFactory.cs
public class NYPizzaIngredientFactory : IIngredientsFactory
{
    public Cheese CreateCheese()
    {
        return new MozzarellaCheese();
    }
    public Clams CreateClam()
    {
        return new FreshClams();
    }
    public Dough CreateDough()
    {
        return new ThinCrustDough();
    }
    public Pepperoni CreatePepperoni()
    {
        return new Pepperoni();
    }
    public Sauce CreateSauce()
    {
        return new MarinaraSauce();
    }
    public Veggies[] CreateVeggies()
    {
        return new Veggies[] { new GarlicVeggie(), newOnionVeggie() };
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Now you can create your own ChicagoPizzaIngredientsFactory by implementing Ingredients.

Step 4: For Ingredients I have used class inheritance for implementing different type of ingredients. Let see how I implemented this.

// filePath: Factory\Ingredients\Cheese.cs
public class Cheese
{
}

// filePath: Factory\Ingredients\Categories\ReggianoCheese.cs
public class ReggianoCheese : Cheese
{
}

// filePath: Factory\Ingredients\Categories\MozzarellaCheese.cs
public class MozzarellaCheese : Cheese
{
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Follow the same order of this category and create you own classes for Clams, Dough, Pepperoni, Sauce and Veggies

Step 6: We have to change the pizza categories for using Ingredients factory and creating pizza.

// filePath: PizzaItems\Pizza.cs
public abstract class Pizza
{
    public string name { get; set; }
    public Dough dough { get; set; }
    public Sauce sauce { get; set; }
    public Veggies[] Veggies { get; set; }
    public Cheese cheese { get; set; }
    public Clams clams { get; set; }
    public abstract void prepare();
    public virtual void bake()
    {
        Console.WriteLine("Bake for 25 minute at 350.");
    }
    public virtual void cut(string cutStyle)
    {
        Console.WriteLine("Cutting the pizza into " +cutStyle + " slices.");
    }
    public virtual void box()
    {
        Console.WriteLine("Place pizza in official PizzaStore box.");
    }
    public void setName(string name)
    {
        this.name = name;
    }
    public string getName()
    {
        return name;
    }
}

// filePath: PizzaItems\Types\CheesePizza.cs
public class CheesePizza : Pizza
{
    private readonly IIngredientsFactory _ingredientFactory;

    public CheesePizza(IIngredientsFactory ingredientFactory)
    {
        _ingredientFactory = ingredientFactory;
    }
    public override void prepare()
    {
        Console.WriteLine("Preparing " + name);
        dough = _ingredientFactory.CreateDough();
        sauce = _ingredientFactory.CreateSauce();
        cheese = _ingredientFactory.CreateCheese();
        clams = _ingredientFactory.CreateClam();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Sit back and relax a bit, now our ingredients factory implementation is completed, so lets pass it to our regional factories. I'm implementing it on NY Pizza Factory you can implement in your Chicago Pizza Factory.

public class NYStylePizzaStore : PizzaStore
{
    public override Pizza CreatePizza(string type)
    {
        Pizza pizza = null;
        IIngredientsFactory ingredientsFactory = newNYPizzaIngredientFactory();
        switch (type)
        {
            case "Cheese":
                pizza = new CheesePizza(ingredientsFactory);
                pizza.setName("NY StyleCheese Pizza");
                break;
            case "Clam":
                pizza = new ClamPizza(ingredientsFactory);
                pizza.setName("NY StyleClam Pizza");
                break;
            default:
                Console.WriteLine("Please select valid pizza type.");
                break;
        }
        return pizza;
    }
}
Enter fullscreen mode Exit fullscreen mode

Share your view

If you want me to write more on design patterns please feel free to comment. It make me feel appreciated.
Also, mention patterns you want to learn.

Top comments (0)