Design Patterns – ‘Abstract Factory’

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

An AbstractFactory is a class that exists to create instances of another class. Described on page 87 of the DesignPatternsBook.

Typically, if you want to construct instances of a class, where the class is selected at run time, you…

  1. Create one AbstractFactory class for each existing class (or group of related classes) you wish to create.
  2. Have a polymorphic “create instance” method on each AbstractFactory class, conforming to a common method signature, used to create instances of the corresponding class.
  3. Store and pass around instances of the AbstractFactory class to control selection of the class to create.

Suppose an abstract class wants to hide its sub class name and its instantiation. If we request one static method of the class that return its sub class object.

 abstract class AA
 {
    static AA getInstance()
    {
    return new A();
    }
 }

 class A extends AA
 {

 }

 class Client
 {
 AA aa=AA.getInstance();
 aa.method();
 }

Abstract Factory pattern — Structural example

I thought of providing a simple UML diagram and sample code, so that you will understand the flow in more detail.

UML class diagram for Products

 

<div>
// Abstract Factory pattern -- Structural example

using System;

namespace MyDesignPatterns.Abstract.Structural

{

  /// <summary>

  /// MainApp startup class for Structural

  /// Abstract Factory Design Pattern.

  /// </summary>

  class MainApp

  {

    /// <summary>

    /// Entry point into console application.

    /// </summary>

    public static void Main()

    {

      // Abstract factory #1

      AbstractFactory factory1 = new ConcreteFactory1();

      Client client1 = new Client(factory1);

      client1.Run();

      // Abstract factory #2

      AbstractFactory factory2 = new ConcreteFactory2();

      Client client2 = new Client(factory2);

      client2.Run();

      // Wait for user input

      Console.ReadKey();

    }

  }

  /// <summary>

  /// The 'AbstractFactory' abstract class

  /// </summary>

  abstract class AbstractFactory

  {

    public abstract AbstractProductA CreateProductA();

    public abstract AbstractProductB CreateProductB();

  }

  /// <summary>

  /// The 'ConcreteFactory1' class

  /// </summary>

  class ConcreteFactory1 : AbstractFactory

  {

    public override AbstractProductA CreateProductA()

    {

      return new ProductA1();

    }

    public override AbstractProductB CreateProductB()

    {

      return new ProductB1();

    }

  }

  /// <summary>

  /// The 'ConcreteFactory2' class

  /// </summary>

  class ConcreteFactory2 : AbstractFactory

  {

    public override AbstractProductA CreateProductA()

    {

      return new ProductA2();

    }

    public override AbstractProductB CreateProductB()

    {

      return new ProductB2();

    }

  }

  /// <summary>

  /// The 'AbstractProductA' abstract class

  /// </summary>

  abstract class AbstractProductA

  {

  }

  /// <summary>

  /// The 'AbstractProductB' abstract class

  /// </summary>

  abstract class AbstractProductB

  {

    public abstract void Interact(AbstractProductA a);

  }

  /// <summary>

  /// The 'ProductA1' class

  /// </summary>

  class ProductA1 : AbstractProductA

  {

  }

  /// <summary>

  /// The 'ProductB1' class

  /// </summary>

  class ProductB1 : AbstractProductB

  {

    public override void Interact(AbstractProductA a)

    {

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

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

    }

  }

  /// <summary>

  /// The 'ProductA2' class

  /// </summary>

  class ProductA2 : AbstractProductA

  {

  }

  /// <summary>

  /// The 'ProductB2' class

  /// </summary>

  class ProductB2 : AbstractProductB

  {

    public override void Interact(AbstractProductA a)

    {

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

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

    }

  }

  /// <summary>

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

  /// </summary>

  class Client

  {

    private AbstractProductA _abstractProductA;

    private AbstractProductB _abstractProductB;

    // Constructor

    public Client(AbstractFactory factory)

    {

      _abstractProductB = factory.CreateProductB();

      _abstractProductA = factory.CreateProductA();

    }

    public void Run()

    {

      _abstractProductB.Interact(_abstractProductA);

    }

  }

}
 </div>
 

Output

ProductB1 interacts with ProductA1

ProductB2 interacts with ProductA2

The classes and/or objects participating in this pattern are :
  • AbstractFactory (AbstractFactory)
    • declares an interface for operations that create abstract products
  • ConcreteFactory (ConcreteFactory1, ConcreteFactory2)
    • implements the operations to create concrete product objects
  • AbstractProduct (AbstractProductA, AbstractProductB)
    • declares an interface for a type of product object
  • Product (ProductA1, ProductA2, ProductB1, ProductB2)
    • defines a product object to be created by the corresponding concrete factory
    • implements the AbstractProductA and AbstractProductB interfaces
  • Client (AnimalWorld)
    • uses interfaces declared by AbstractFactory and AbstractProduct classes