This is the next pattern in my "Design Patterns series". "Abstract Factory Pattern" can be found here.
Factory Method Pattern creates an instance of several derived classes. Centralize creation of an object of specific type choosing one of the several implementations. It is called factory pattern as it is responsible for "manufacturing" an object. The Factory pattern is meant to give you the ability to generically construct objects rather than explicitly declare what you want to create via the "new" keyword; you defer to a factory and take what it gives you. Scenarios of use:
- A class can't anticipate which kind of class of objects it must create.
- A class uses its subclasses to specify which objects it creates.
- You want to localize the knowledge of which class gets created.
I'll try to explain the pattern by means of following example; consider you have real world problem of building a house, where you have to create doors, windows and walls.
static void Main(string[] args)
{
Console.WriteLine("Please choose objects from the below to built:");
Console.WriteLine("1. Door");
Console.WriteLine("2. Window");
int objectType = Convert.ToInt16(Console.ReadLine());
if (objectType == 1)
{
DoorFactory objectDoorFactory = new DoorFactory();
objectDoorFactory.Print();
}
else if (objectType == 2)
{
WindowFactory objectWindowFactory = new WindowFactory();
objectWindowFactory.Print();
}
Thread.Sleep(5000);
}
In above class the user is prompted to choose which object he/she wants to create, based on the choice either of the two classes (mentioned below) object gets created.
class DoorFactory
{
public void Print()
{
Console.WriteLine("You built a door");
}
}
class WindowFactory
{
public void Print()
{
Console.WriteLine("You built a window");
}
}
Problem with above code:
- Many keywords are scattered in the client (Main(string[] args) above). The client is loaded with lots of object creations which can cause complexities to the client logic.
- Secondly, client code need to aware of all types of objects. Consider a scenario, if client want to add new object creation say "Walls" (a new class WindowFactory) then we need to create object of it as well.
Solution:
- First problem is due to the direct contact of client to the "WindowFactory" and "DoorFactory", that was causing lots of new keywords. It is removed by inserting a new class say "ObjectFactory" which will be responsible for object creation. There will be no direct contact between client and the "WindowFactory" and "DoorFactory" classes.
- If we analyse the second problem, we found this problem was because the client code is aware of both the concrete classes needed it to recompile when new object ("Walls") type added. This can be removed by introducing a new interface say "IObjectFactory".
Both the concrete classes inherit and implement the "IObjectFactory". The client references only the "IObjectFactory" interface which results in no connection between client and the concrete classes.
This is done as follows:
Class Program:
static void Main(string[] args)
{
Console.WriteLine("Please choose objects from the below to built:");
Console.WriteLine("1. Door");
Console.WriteLine("2. Window");
Console.WriteLine("3. Walls");
int objectType = Convert.ToInt16(Console.ReadLine());
IObjectFactory objectFactory = null;
if (objectType == 1)
{
objectFactory = ObjectFactory.GetObject(1);
}
else if (objectType == 2)
{
objectFactory = ObjectFactory.GetObject(2);
}
else if (objectType == 3)
{
objectFactory = ObjectFactory.GetObject(3);
}
if (objectFactory != null)
{
objectFactory.Print();
Thread.Sleep(5000);
}
}
Class ObjectFactory:
class ObjectFactory
{
static public IObjectFactory GetObject(int objectType)
{
if (objectType == 1)
{ return (new DoorFactory()); }
else if(objectType==2)
{ return (new WindowFactory()); }
else if (objectType == 3)
{ return (new WallFactory()); }
else
return null;
}
}
Interface IObjectFactory:
public interface IObjectFactory
{
void Print();
}
Class DoorFactory:
class DoorFactory : IObjectFactory
{
#region IObjectFactory Members
public void Print()
{
Console.WriteLine("You built a door");
}
#endregion
}
Class WindowFactory:
class WindowFactory : IObjectFactory
{
#region IObjectFactory Members
public void Print()
{
Console.WriteLine("You built a window");
}
#endregion
}
Class WallFactory:
class WallFactory : IObjectFactory
{
#region IObjectFactory Members
public void Print()
{
Console.WriteLine("You built walls");
}
#endregion
}
Hope it would help!!
More patterns in next post.