Let’s begin with a story of 2 brothers Bill and Steve. Both love Pizza and Ice Cream. They go to a Food Court which has Pizza outlets like Pizza Hut and Dominos Pizza and Ice Cream Parlours like Baskin Robbins and Mikey.
Taking this real world pattern into our Software design by creating classes. In this context, Food Court will be our FoodFactory abstract class that creates 2 abstract Products Pizza and Ice Cream. The Food Court has 2 sections Fun and Frolic. Bill goes for Fun and Steve goes to Frolic.
public abstract class FoodFactory
{
public abstract Pizza BakePizza();
public abstract IceCream MakeIceCream();
}
Create an Abstract Products folder and add the following 2 classes:
public class Pizza {
}
public class IceCream {
}
Create a Products Folder and add the following classes:
public class DominosPizza: Pizza
{
public DominosPizza()
{
}
}
public class PizzaHut: Pizza
{
public PizzaHut()
{
}
}
public class Mikey: IceCream
{
public Mikey()
{
}
}
public class BaskinRobbins: IceCream
{
public BaskinRobbins()
{
}
}
Now, suppose Fun section has Pizza Hut and Mikey and Frolic has Dominos Pizza and Baskin Robbins. Create a folder Factories and under that add the following classes:
class FunFoodFactory : FoodFactory
{
public override Pizza BakePizza()
{
return new PizzaHut();
}
public override IceCream MakeIceCream()
{
return new Mikey();
}
}
public class FrolicFoodFactory : FoodFactory
{
public override Pizza BakePizza()
{
return new DominosPizza();
}
public override IceCream MakeIceCream()
{
return new BaskinRobbins();
}
}
Now the 2 Good brothers start having fun. Create a class called GoodBrothers as below:
public class GoodBrothers
{
private readonly Pizza _pizza;
private readonly IceCream _icecream;
public GoodBrothers(FoodFactory factory)
{
_pizza = factory.BakePizza();
_icecream = factory.MakeIceCream();
}
public string WhatDidYouHaveToday()
{
return $"Today I ate at {_pizza.GetType().Name} and {_icecream.GetType().Name}";
}
}
From the main class we ask them What did you have today?
class Program
{
static void Main(string[] args)
{
GoodBrothers Bill = new GoodBrothers(new FunFoodFactory());
Console.WriteLine($"Bill: {Bill.WhatDidYouHaveToday()}");
GoodBrothers Steve = new GoodBrothers(new FrolicFoodFactory());
Console.WriteLine($"Steve: {Steve.WhatDidYouHaveToday()}");
Console.ReadKey();
}
}
Output:
Bill: Today I ate at PizzaHut and Mikey
Steve: Today I ate at DominosPizza and BaskinRobbins
A similar example for Abstract Factory pattern can be for a Clothes Factory abstract class which creates abstract Products like Shirts and Trousers. A Businessman may buy from ElegantFactory and a student may buy from CasualFactory. Shirts can be of types Formal and PoloTs and Trousers can be of type Suit and Jeans.
The ElegantFactory will return types Formal Shirt and Suit Trousers. CasualFactory will return types PoloTs and Jeans. We can create a Client class like GoodBrothers that receives the ClothesFactory reference in it’s constructor to create a Shirt and Trouser for the Businessman and Student and so on.