Factory pattern with generics

This post supposes that you have some knowledge about generics and what the Factory pattern are. 

The Factory pattern is a powerful creational pattern; it provides a way to instantiate classes dynamically at run time (For more info http://www.dofactory.com/Patterns/Patterns.aspx).

 

Generics opens a lot of new ways in order to implement many of the GOF patterns. But I was looking for an implementation of the factory pattern using generics and I didn't find something that solve my case.

 

If we need to create a factory class that supports only one kind of object obviously the implementation of the factory using generics is easy.

 

      public interface IFactory<T>

      {

            T Create();

      }

 

      public class Factory<T> : IFactory<T> where T : new()

      {

            public T Create()

            {

                  return new T();

            }

      }

 

 

But as Hugo Troche explain in this article

 “Generics change the basic implementation dynamic of factories. With factories the system defines the type of an object at run time. With generics the compiler has to be able to figure out the type of all objects at compile time”

 

The problem is when we need to create (as the pattern say) a different object depending on a key.

 

Let me explain a bit more what I’m going to try to solve. Suppose the common use case for a factory pattern:

 

public interface ICar

      {

            string Name { get; }

      }

 

      public class Ford : ICar

      {

            #region ICar Members

 

            public string Name

            {

                  get { return "Ford"; }

            }

 

 

            #endregion

      }

 

      public class Fiat : ICar

      {    

            #region ICar Members

 

            public string Name

            {

                  get { return "Fiat"; }

            }

 

            #endregion

     

      }

     

 

Hugo in his article found a solution using a combination of the Factory and a Chain of Responsibility patterns. It is a cool solution but you should change your classes definitions in order to implement the Chain of responsibility.

I was looking a solution for this use case with the following characteristics:

 

-         The factory should have a strong typed method that returns a Car. (ie Car Create(string name) )

-         The factory never rise an InvalidCastException

-         It should be implemented using Generics in order to use it for other cases.

 

So I started defining the interface for the factory

 

      public interface IFactory<K, T> where K : IComparable

      {

            T Create();

      }

 

After I defined a helper interface for the items in the factory

 

      public interface IFactoryElement

      {

            object New();

      }

 

An implementation of the IFactoryElement

 

      public class FactoryElement<T> : IFactoryElement

                                          where T : new()

      {

 

            public object New()

            {

                  return new T();

            }

 

      }

 

As you can see the New method returns an object and not T. If it returns T we are defining that the Create method of the factory will return always something of type T.

 

 

Now the factory

 

      public class Factory<K, T> : IFactory<K, T> where K : IComparable

      {

            /// Elements that can be created

            Dictionary<K, IFactoryElement> elements = new Dictionary<K, IFactoryElement>();

 

            /// <summary>

            ///  Add a new creatable kind of object to the factory. Here is the key with the beauty of the constrains in generics. Look that we are saying that V should be derived of T and it must be creatable

            /// </summary>

            public void Add<V>(K key) where V : T, new()

            {

                  elements.Add(key, new FactoryElement<V>());

            }

 

            public T Create(K key)

            {

                  if (elements.ContainsKey(key))

                  {

                        return (T) elements[key].New();

                  }

                  throw new ArgumentException();

            }

      }

 

Note that the Create method never raise an InvalidCastException because elements[key] is going to return something of type V, and T is the base class of V !!

     

 

So for the use case of the cars I can use my generic factory in this way:

 

      public class CarFactory

      {

            Factory<string, ICar> internalFactory = new Factory<string, ICar>();

 

            public class CarFactory()

            {

                  internalFactory.Add<Fiat>("fiat");

                  internalFactory.Add<Ford>("ford");

            }

 

            public ICar Create(string carType)

            {

                  return internalFactory.Create(carType);

            }

      }

 

I could use directly the factory without this class, the only issue is that it has the Add method as public.

Comments in order to improve this implementation are welcome !!

 

 

 

 

 

 

 

11 Comments

  • Why make the caller create and pass a FactoryElement to Add()? Instead:



    public void Add&lt;V&gt;(K key) where V : T, new()

    {

    elements.Add(key, , new FactoryElement&lt;V&gt;());

    }



    This way the FactoryElement class needn't be visible to the caller at all.

  • Hi,



    Because 3 am is to late for programming ;) I update the post with your comment.



    Thank you !!

  • Why do you need the factory element or the dictionary? Will this work:

    public static class Factory where T : I, new()
    {
    public static I Create()
    {
    return new T();
    }
    }

    I represents an interface that T extends.

  • Great article! Thanks!

  • Hmmm...
    We can use the Func that would simplify the factory (only one helper generic class required now):

    #region generic factory

    public class Factory where K : IComparable
    {
    Dictionary<K, Func> elements = new Dictionary<K, Func>();

    public void Add(K key) where V : T, new()
    {
    elements.Add(key, ()=>new V());
    }

    public T Create(K key)
    {
    if (elements.ContainsKey(key))
    {
    return elements[key]();
    }
    throw new ArgumentException();
    }
    }

    #endregion

  • And now we can simplify CarFactory too:

    public class CarFactory : Factory
    {
    public class CarFactory()
    {
    Add("fiat");
    Add("ford");
    }
    }

  • :c I only have VS2005.. could you simplify this expression

    elements.Add(key, ()=>new V());

    I would like not a lambda expression but using delegate..

    forgive my being novice to this kind of programming..

    Thanks,
    janverge

  • ()=>new V()

    =

    delegate () {return new V();}

  • But if you are like me new to all this, then you want to know why the compiler is not happy:

    In the final class this:

    public class CarFactory()

    {

    internalFactory.Add("fiat");

    internalFactory.Add("ford");

    }


    should be:
    public CarFactory()

    {

    internalFactory.Add("fiat");

    internalFactory.Add("ford");

    }

  • I like it and its comments.
    Thanks!
    Can I say an abstract factory pattern is a design pattern/concept and generics is a strong-typed feature of a language?
    And what we have shown is an implementation of factory pattern using C# generics?
    Are there generics in Java/C++?
    Jeff

  • This code tested.
    Dictionary<K, Func> elements = new Dictionary<K, Func>(); is replaced by
    private Dictionary GenericDictionary = new Dictionary();
    public Dictionary GetGenericDictionary { get{return GenericDictionary;} }
    and also return GenericDictionary[key]();
    replaced by return GenericDictionary[key];

    namespace ConsoleAppGenericFactory
    {
    public class GenericFactory where K : IComparable
    {
    private Dictionary GenericDictionary = new Dictionary();
    public Dictionary GetGenericDictionary { get{return GenericDictionary;} }
    public void Add(K key) where V : T, new()
    {
    GenericDictionary.Add(key, new V());
    }
    public T Create(K key)
    {
    if (GenericDictionary.ContainsKey(key))
    {
    return GenericDictionary[key];
    }
    throw new ArgumentException();
    }
    }
    }
    class Program
    {
    static void Main(string[] args)
    {


    ConcreteCarFactory f = new ConcreteCarFactory();
    var cars= from c in f.GetGenericDictionary
    select new {KeyName=c.Key, ValueName=c.Value.Name, Type=c.Value.GetType().ToString()};
    // c.Value.Name will do anonymous type referencing ((ICar)(c.Value)).Name
    Console.WriteLine("Key, Name, Type");
    foreach (var c in cars)
    {
    Console.WriteLine("{0},{1},{2}",c.KeyName,c.ValueName,c.Type);
    }
    Console.ReadLine();
    }
    }

Comments have been disabled for this content.