Wednesday 21 August 2013

Factory Pattern vs Factory Method Pattern vs Abstract Factory Pattern

Factory Pattern

Suppose we have two classes ClassA and ClassB

Now i am having a Third Class or suppose a Web Page where i need to create objects of both of these class(ClassA & ClassB). So what we can do here simply is:

ClassA a = new ClassA();
ClassB b = new ClassB();

But it is not a good way as the Client or the consumer is directly having permission to create an object or the you can say Client or Consumer should not be responsible for creating the objects. This is because if something changes in the way of initialization (Creation of objects) then we need to change everywhere in the consumer files wherever we are initializing these classes. So best way, is to give out the responsibility of creation of objects to a new class. This is known as Factory Pattern. So whenever there is a change in the process of initialization we need to makes changes only in factory Pattern.

So, for this we can create a Factory Class which will have the responsibility of creating Objects. It can be either parameterised (Open-Close Principle is not followed) or can be based on reflection.

Parameterised Factory:

    public class SampleClass
    {
    }

    public class ClassA : SampleClass
    {

    }

    public class ClassB : SampleClass
    {

    }

    public class Factory
    {
        public SampleClass Create(int classType)
        {
            SampleClass classObject = new SampleClass();
            if (classType == 1)
            {
                classObject = new ClassA();
            }
            if (classType == 2)
            {
                classObject = new ClassB();
            }
            //So On for every Class
            return classObject;
        }
    }

So now for creating object code will be something like this:

SampleClass a = new Factory().Create(1);
SampleClass b = new Factory().Create(2);

But this breaks open close principle, so we can do it by reflection

Using Reflection:

    public class SampleClass
    {
    }

    public class ClassA : SampleClass
    {

    }

    public class ClassB : SampleClass
    {

    }

    public class Factory
    {
        public SampleClass Create(string className)
        {
            SampleClass instance = new SampleClass();
            var requiredClass = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where string.Equals(type.Name, className, StringComparison.OrdinalIgnoreCase)
                                 select type).FirstOrDefault();

            if (requiredClass != null)
            {
                instance = (SampleClass)Activator.CreateInstance(requiredClass);
            }

            return instance;
        }
    }

So now for creating object code will be something like this:

SampleClass a = new Factory().Create(“ClassA”);
SampleClass b = new Factory().Create(“ClassB”);

Now we don’t need to change Factory class, but right now we are having type of classes “SampleClass” that is our both the classes are inherited by this “SampleClass”, what if a new base class comes into picture, then we need to have multiple factories and which is fine (But then the consumer should know that which factory needs to be referred to get the objects of that type and also each factory can have different methods which actually create the object and returns them, example: Right now Factory class which we created above is having a method “Create” but in future someone can create a new Factory say “FactoryNew” to get the objects of some other type and the method which will be creating and returning the object can be named as “CreateNew”). So here comes the Factory Method and Abstract factory pattern into the picture.

Factory Method

It’s the way of imposing that every Factory should have a method “Create” which should return the desired object(Sub classes that are original factories can decide which type of object needs to be returned)
It helps the consumer to directly call a method “Create” to get the object irrespective of which factory going to be used.

Here goes the code:

    public class SampleClass
    {
    }

    public class SampleClassA : SampleClass
    {
    }

    public class SampleClassB : SampleClass
    {
    }

    public class ClassA : SampleClassA
    {

    }

    public class ClassB : SampleClassA
    {

    }

    public class ClassC : SampleClassB
    {

    }

    public class ClassD : SampleClassB
    {

    }

    public abstract class Factory
    {
        public SampleClass GetObject(string className)
        {
            return CreateObject(className);

        }

        //Acting as a Factory Method
        protected abstract SampleClass CreateObject(string className);
    }

    public class FactoryA : Factory
    {
        protected SampleClass CreateObject(string className)
        {
            SampleClass instance = new SampleClassA();
            var requiredClass = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where string.Equals(type.Name, className, StringComparison.OrdinalIgnoreCase)
                                 select type).FirstOrDefault();

            if (requiredClass != null)
            {
                instance = (SampleClassA)Activator.CreateInstance(requiredClass);
            }

            return instance;
        }
    }

    public class FactoryB : Factory
    {
        protected SampleClass CreateObject(string className)
        {
            SampleClass instance = new SampleClassB();
            var requiredClass = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where string.Equals(type.Name, className, StringComparison.OrdinalIgnoreCase)
                                 select type).FirstOrDefault();

            if (requiredClass != null)
            {
                instance = (SampleClassB)Activator.CreateInstance(requiredClass);
            }

            return instance;
        }
    }

So now for creating object code will be something like this:

SampleClass a = new FactoryA().GetObject(“ClassA”);
SampleClass b = new FactoryA().GetObject(“ClassB”);
SampleClass c = new FactoryB().GetObject(“ClassC”);
SampleClass d = new FactoryB().GetObject(“ClassD”);

So what’s the problem now which still persists, any guesses?????

As of now everything is perfect just one problem is remaining and that is client or the consumer has to create the objects of factory (knowing that which factory will return which type of object). This problem can be eliminated by adding one more level of abstraction on Factories (i.e. Factory for numerous factories). It that case consumer don’t have to create the object of factory themselves they will just provide which object they need and based on that it’s the task of the parent factory to decide which factory needs to be initiated to create that kind of object). So here comes the Abstract Factory into picture.

Abstract Factory:
I don’t think I need to explain what Abstract Factory pattern is and why we need it. But anyways, Abstract Factory is used to provide one more level of modularization by which consumer don’t have to worry to create an instance of the Factory also, the responsibility goes inside the Parent Factory

Here goes the Code:

    public class SampleClass
    {
    }

    public class SampleClassA : SampleClass
    {
    }

    public class SampleClassB : SampleClass
    {
    }

    public class ClassA : SampleClassA
    {

    }

    public class ClassB : SampleClassA
    {

    }

    public class ClassC : SampleClassB
    {

    }

    public class ClassD : SampleClassB
    {

    }

    public class Factory
    {
        public SampleClass GetObject(string className)
        {
            SampleClass instance = new SampleClass();

            //Here we can have Enums or XML as Depedency Injection Container have XML to get which factory needs to be initiated for which class
            //So we can read that value and use reflection code to initiate that Factory and call its method "CreateObject" here goes the code for that

            //Suppose we get the name of the factory class from XML and put it ninto the string, consider we get "FactoryA" in this example
            string factoryName = "FactoryA";

            var requiredFactory = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                   from type in assembly.GetTypes()
                                   where string.Equals(type.Name, factoryName, StringComparison.OrdinalIgnoreCase)
                                   select type).FirstOrDefault();

            if (requiredFactory != null)
            {
                object factoryInstance = Activator.CreateInstance(requiredFactory);
                // Get the operation's method, invoke it, and get the return value, Factory knows method name is CreateObject
                var methodInfo = factoryInstance.GetType().GetMethod("CreateObject");

                object[] operationParameters = new object[] { className };
                instance = (SampleClass)methodInfo.Invoke(factoryInstance, System.Reflection.BindingFlags.InvokeMethod, null, operationParameters, null);
            }

            return instance;
        }
    }

    public interface IFactory
    {
        SampleClass CreateObject(string className);
    }

    public class FactoryA : IFactory
    {
        public SampleClass CreateObject(string className)
        {
            SampleClass instance = new SampleClassA();
            var requiredClass = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where string.Equals(type.Name, className, StringComparison.OrdinalIgnoreCase)
                                 select type).FirstOrDefault();

            if (requiredClass != null)
            {
                instance = (SampleClassA)Activator.CreateInstance(requiredClass);
            }

            return instance;
        }
    }

    public class FactoryB : IFactory
    {
        public SampleClass CreateObject(string className)
        {
            SampleClass instance = new SampleClassB();
            var requiredClass = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                 from type in assembly.GetTypes()
                                 where string.Equals(type.Name, className, StringComparison.OrdinalIgnoreCase)
                                 select type).FirstOrDefault();

            if (requiredClass != null)
            {
                instance = (SampleClassB)Activator.CreateInstance(requiredClass);
            }

            return instance;
        }
    }

So now for creating object code will be something like this:

SampleClass a = new Factory().GetObject(“ClassA”);
SampleClass b = new Factory().GetObject(“ClassB”);
SampleClass c = new Factory().GetObject(“ClassC”);
SampleClass d = new Factory().GetObject(“ClassD”);

Note: Abstract Factory is normally not required in small applications.


I hope it helps you in distinguishing now what is the difference between Factor Pattern, Factory Method Pattern and Abstract Factory.

No comments:

Post a Comment