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.
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);
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”);
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 b = new FactoryA().GetObject(“ClassB”);
SampleClass c = new FactoryB().GetObject(“ClassC”);
SampleClass d = new FactoryB().GetObject(“ClassD”);
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 b = new Factory().GetObject(“ClassB”);
SampleClass c = new Factory().GetObject(“ClassC”);
SampleClass d = new Factory().GetObject(“ClassD”);
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