Abstract Factory

 Summary:  Provide an interface for creating families of related or dependent objects without specifying their concrete classes.




Participants

The classes and objects participating in this pattern are:

  • AbstractFactory  (ContinentFactory)
    • declares an interface for operations that create abstract products
  • ConcreteFactory   (AfricaFactory, AmericaFactory)
    • implements the operations to create concrete product objects
  • AbstractProduct   (Herbivore, Carnivore)
    • declares an interface for a type of product object
  • Product  (Wildebeest, Lion, Bison, Wolf)
    • defines a product object to be created by the corresponding concrete factory
    • implements the AbstractProduct interface
  • Client  (AnimalWorld)
    • uses interfaces declared by AbstractFactory and AbstractProduct classes

Structural code in C#

This structural code demonstrates the Abstract Factory pattern creating parallel hierarchies of objects. Object creation has been abstracted and there is no need for hard-coded class names in the client code.

  1. using System;

  2.  

  3. namespace DoFactory.GangOfFour.Abstract.Structural

  4. {

  5.   /// <summary>

  6.   /// MainApp startup class for Structural

  7.   /// Abstract Factory Design Pattern.

  8.   /// </summary>

  9.   class MainApp

  10.   {

  11.     /// <summary>

  12.     /// Entry point into console application.

  13.     /// </summary>

  14.     public static void Main()

  15.     {

  16.       // Abstract factory #1

  17.       AbstractFactory factory1 = new ConcreteFactory1();

  18.       Client client1 = new Client(factory1);

  19.       client1.Run();

  20.  

  21.       // Abstract factory #2

  22.       AbstractFactory factory2 = new ConcreteFactory2();

  23.       Client client2 = new Client(factory2);

  24.       client2.Run();

  25.  

  26.       // Wait for user input

  27.       Console.ReadKey();

  28.     }

  29.   }

  30.  

  31.   /// <summary>

  32.   /// The 'AbstractFactory' abstract class

  33.   /// </summary>

  34.   abstract class AbstractFactory

  35.   {

  36.     public abstract AbstractProductA CreateProductA();

  37.     public abstract AbstractProductB CreateProductB();

  38.   }

  39.  

  40.  

  41.   /// <summary>

  42.   /// The 'ConcreteFactory1' class

  43.   /// </summary>

  44.   class ConcreteFactory1 : AbstractFactory

  45.   {

  46.     public override AbstractProductA CreateProductA()

  47.     {

  48.       return new ProductA1();

  49.     }

  50.     public override AbstractProductB CreateProductB()

  51.     {

  52.       return new ProductB1();

  53.     }

  54.   }

  55.  

  56.   /// <summary>

  57.   /// The 'ConcreteFactory2' class

  58.   /// </summary>

  59.   class ConcreteFactory2 : AbstractFactory

  60.   {

  61.     public override AbstractProductA CreateProductA()

  62.     {

  63.       return new ProductA2();

  64.     }

  65.     public override AbstractProductB CreateProductB()

  66.     {

  67.       return new ProductB2();

  68.     }

  69.   }

  70.  

  71.   /// <summary>

  72.   /// The 'AbstractProductA' abstract class

  73.   /// </summary>

  74.   abstract class AbstractProductA

  75.   {

  76.   }

  77.  

  78.   /// <summary>

  79.   /// The 'AbstractProductB' abstract class

  80.   /// </summary>

  81.   abstract class AbstractProductB

  82.   {

  83.     public abstract void Interact(AbstractProductA a);

  84.   }

  85.  

  86.  

  87.   /// <summary>

  88.   /// The 'ProductA1' class

  89.   /// </summary>

  90.   class ProductA1 : AbstractProductA

  91.   {

  92.   }

  93.  

  94.   /// <summary>

  95.   /// The 'ProductB1' class

  96.   /// </summary>

  97.   class ProductB1 : AbstractProductB

  98.   {

  99.     public override void Interact(AbstractProductA a)

  100.     {

  101.       Console.WriteLine(this.GetType().Name +

  102.         " interacts with " + a.GetType().Name);

  103.     }

  104.   }

  105.  

  106.   /// <summary>

  107.   /// The 'ProductA2' class

  108.   /// </summary>

  109.   class ProductA2 : AbstractProductA

  110.   {

  111.   }

  112.  

  113.   /// <summary>

  114.   /// The 'ProductB2' class

  115.   /// </summary>

  116.   class ProductB2 : AbstractProductB

  117.   {

  118.     public override void Interact(AbstractProductA a)

  119.     {

  120.       Console.WriteLine(this.GetType().Name +

  121.         " interacts with " + a.GetType().Name);

  122.     }

  123.   }

  124.  

  125.   /// <summary>

  126.   /// The 'Client' class. Interaction environment for the products.

  127.   /// </summary>

  128.   class Client

  129.   {

  130.     private AbstractProductA _abstractProductA;

  131.     private AbstractProductB _abstractProductB;

  132.  

  133.     // Constructor

  134.     public Client(AbstractFactory factory)

  135.     {

  136.       _abstractProductB = factory.CreateProductB();

  137.       _abstractProductA = factory.CreateProductA();

  138.     }

  139.  

  140.     public void Run()

  141.     {

  142.       _abstractProductB.Interact(_abstractProductA);

  143.     }

  144.   }

  145. }

  146.  

  147.  
Output
ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2

Real-world code in C#

This real-world code demonstrates the creation of different animal worlds for a computer game using different factories. Although the animals created by the Continent factories are different, the interactions among the animals remain the same.

  1. using System;

  2.  

  3. namespace DoFactory.GangOfFour.Abstract.RealWorld

  4. {

  5.   /// <summary>

  6.   /// MainApp startup class for Real-World

  7.   /// Abstract Factory Design Pattern.

  8.   /// </summary>

  9.   class MainApp

  10.   {

  11.     /// <summary>

  12.     /// Entry point into console application.

  13.     /// </summary>

  14.     public static void Main()

  15.     {

  16.       // Create and run the African animal world

  17.       ContinentFactory africa = new AfricaFactory();

  18.       AnimalWorld world = new AnimalWorld(africa);

  19.       world.RunFoodChain();

  20.  

  21.       // Create and run the American animal world

  22.       ContinentFactory america = new AmericaFactory();

  23.       world = new AnimalWorld(america);

  24.       world.RunFoodChain();

  25.  

  26.       // Wait for user input

  27.       Console.ReadKey();

  28.     }

  29.   }

  30.  

  31.  

  32.   /// <summary>

  33.   /// The 'AbstractFactory' abstract class

  34.   /// </summary>

  35.   abstract class ContinentFactory

  36.   {

  37.     public abstract Herbivore CreateHerbivore();

  38.     public abstract Carnivore CreateCarnivore();

  39.   }

  40.  

  41.   /// <summary>

  42.   /// The 'ConcreteFactory1' class

  43.   /// </summary>

  44.   class AfricaFactory : ContinentFactory

  45.   {

  46.     public override Herbivore CreateHerbivore()

  47.     {

  48.       return new Wildebeest();

  49.     }

  50.     public override Carnivore CreateCarnivore()

  51.     {

  52.       return new Lion();

  53.     }

  54.   }

  55.  

  56.   /// <summary>

  57.   /// The 'ConcreteFactory2' class

  58.   /// </summary>

  59.   class AmericaFactory : ContinentFactory

  60.   {

  61.     public override Herbivore CreateHerbivore()

  62.     {

  63.       return new Bison();

  64.     }

  65.     public override Carnivore CreateCarnivore()

  66.     {

  67.       return new Wolf();

  68.     }

  69.   }

  70.  

  71.   /// <summary>

  72.   /// The 'AbstractProductA' abstract class

  73.   /// </summary>

  74.   abstract class Herbivore

  75.   {

  76.   }

  77.  

  78.   /// <summary>

  79.   /// The 'AbstractProductB' abstract class

  80.   /// </summary>

  81.   abstract class Carnivore

  82.   {

  83.     public abstract void Eat(Herbivore h);

  84.   }

  85.  

  86.   /// <summary>

  87.   /// The 'ProductA1' class

  88.   /// </summary>

  89.   class Wildebeest : Herbivore

  90.   {

  91.   }

  92.  

  93.   /// <summary>

  94.   /// The 'ProductB1' class

  95.   /// </summary>

  96.   class Lion : Carnivore

  97.   {

  98.     public override void Eat(Herbivore h)

  99.     {

  100.       // Eat Wildebeest

  101.       Console.WriteLine(this.GetType().Name +

  102.         " eats " + h.GetType().Name);

  103.     }

  104.   }

  105.  

  106.   /// <summary>

  107.   /// The 'ProductA2' class

  108.   /// </summary>

  109.   class Bison : Herbivore

  110.   {

  111.   }

  112.  

  113.   /// <summary>

  114.   /// The 'ProductB2' class

  115.   /// </summary>

  116.   class Wolf : Carnivore

  117.   {

  118.     public override void Eat(Herbivore h)

  119.     {

  120.       // Eat Bison

  121.       Console.WriteLine(this.GetType().Name +

  122.         " eats " + h.GetType().Name);

  123.     }

  124.   }

  125.  

  126.   /// <summary>

  127.   /// The 'Client' class

  128.   /// </summary>

  129.   class AnimalWorld

  130.   {

  131.     private Herbivore _herbivore;

  132.     private Carnivore _carnivore;

  133.  

  134.     // Constructor

  135.     public AnimalWorld(ContinentFactory factory)

  136.     {

  137.       _carnivore = factory.CreateCarnivore();

  138.       _herbivore = factory.CreateHerbivore();

  139.     }

  140.  

  141.     public void RunFoodChain()

  142.     {

  143.       _carnivore.Eat(_herbivore);

  144.     }

  145.   }

  146. }

  147.  
Output

Lion eats Wildebeest
Wolf eats Bison