Monday, November 21, 2011

Abstract Factory Design Pattern

This is some sample code from C# 3.0 Design Patterns by Judith Bishop outlining the Abstract Factory Design Pattern:

using System;

namespace AbstractFactoryPattern {
  //  Abstract Factory        D-J Miller and Judith Bishop Sept 2007
  //  Uses generics to simplify the creation of factories
  
  interface IFactory<Brand>
    where Brand : IBrand {
    IBag CreateBag();
    IShoes CreateShoes();
  }

  // Conctete Factories (both in the same one)
  class Factory<Brand> : IFactory<Brand>
    where Brand : IBrand, new() {
    public IBag CreateBag() {
      return new Bag<Brand>();
    }

    public IShoes CreateShoes() {
      return new Shoes<Brand>();
    }
  }

  // Product 1
  interface IBag {
    string Material { get; }
  }

  // Product 2
  interface IShoes {
    int Price { get; }
  }

  // Concrete Product 1
  class Bag<Brand> : IBag
    where Brand : IBrand, new() {
    private Brand myBrand;
    public Bag() {
      myBrand = new Brand();
    }

    public string Material { get { return myBrand.Material; } }
  }

  // Concrete Product 2
  class Shoes<Brand> : IShoes
    where Brand : IBrand, new() {
      
    private Brand myBrand;
      
    public Shoes() {
      myBrand = new Brand();
    }

    public int Price { get { return myBrand.Price; } }
  }

  interface IBrand {
    int Price { get; }
    string Material { get; }
  }

  class Gucci : IBrand {
    public int Price { get { return 1000; } }
    public string Material { get { return "Crocodile skin"; } }
  }

  class Poochy : IBrand {
    public int Price { get { return new Gucci().Price / 3; } }
    public string Material { get { return "Plastic"; } }
  }

  class Groundcover : IBrand {
    public int Price { get { return 2000; } }
    public string Material { get { return "South african leather"; } }
  }

  class Client<Brand>
    where Brand : IBrand, new() {
    public void ClientMain() { //IFactory<Brand> factory)
      IFactory<Brand> factory = new Factory<Brand>();

      IBag bag = factory.CreateBag();
      IShoes shoes = factory.CreateShoes();

      Console.WriteLine("I bought a Bag which is made from " + bag.Material);
      Console.WriteLine("I bought some shoes which cost " + shoes.Price);
    }
  }

  static class Program {
    static void Main() {
      // Call Client twice
      new Client<Poochy>().ClientMain();
      new Client<Gucci>().ClientMain();
      new Client<Groundcover>().ClientMain();
    }
  }
} 
 
Based on the above code, we can readily notice that this does not differ significantly from the 
Factory Method Design Pattern in that it is still heavily reliant on Interfaces.  In this case,
however, the usage of C# Generics has further simplified the process of specifying
concrete class implementations, thus allowing a Class Name to be specified as a 
parameter rather than an actual concrete class instance.
The Abstract Factory Design pattern primarily differs from the Factory Method class in that
the individual classes or "factories" are responsible for handling the business
logic for processing, whereas in the Factory Method Design Pattern, this is wholly contained
within the logic of a single method.  In addition, the Abstract Factory Design Pattern
is leverage to create a group of related products (in this case, bags and shoes) whereas
the Factory Method also concerned itself with the instantiation of only a single
class based on a common Interface.  Therefore, the abstraction in this case is to the 
level of encapsulating the internal details and logic of creating a "factory" 
rather than creating a specific single class instance.

No comments:

Post a Comment