What is a factory? .. A factory is a place where objects are created. Factory Pattern is a well known pattern which will help you to create objects when the following scenario may arrive.
Suppose we have a factory of cars which builds cars of type Ford, Ambassador, Mclaren, Ferrari. The existing code has a method CreateCar() that takes in cartype as an argument and returns the required Car object. The existing code may be as follows….
public enum CarType{
Ford=0,
Ambassador=1,
Mclaren=2,
Ferrari=3
}
public Car(CarType cartype)
{
if(cartype==CarType.Ford)
{
// return Ford object
}
else if(cartype==CarType.Ambassador)
{
//return Ambassador object
}
…
…
…
}
The above code works pretty well as of now. But it has problems in terms of scalability and maintainability. If now we need to increase the type of cars available, the only way we can do that is to keep on increasing the number of if/else-if constructs. This produces more of un-maintainable code. Here comes the need of Factory Pattern.
Encapsulating the logic inside a CarFactory solves a part of the problem , but our factory also need to be both scalable and maintainable in the sense that it needs to provide a generic solution to creational logic , and not just the current workflow scope.
Now we are increasing our range of cars , as told before. Therefore to start of with are increasing the enum items.
enum CarType
{
Ford,
Mitsubishi,
Ambassador,
Peugot
}
Now we create the required classes
public abstract class Car
{
}
public class Ford:Car
{
}
public class Mitsubishi:Car
{
}
public class Ambassador:Car
{
}
public class Peugot:Car
{
}
Car here is an abstract class that is being inherited by the child classes whose instance we are trying to create.
Now we create the actual CarFactory.
class CarFactory
{
Hashtable _registeredcars = new Hashtable();
Hashtable _loadedcars = new Hashtable();
///<summary>
/// Asscociating the CarType with the actual object
///</summary>
///<param name="cartype"></param>
///<param name="car"></param>
public void Register(CarType cartype,Type car)
{
_registeredcars.Add(cartype,car);
}
public void Register(string cartype,Type car)
{
_registeredcars.Add(cartype,car);
}
public Car CreateCar(CarType cartype)
{
if(_loadedcars[cartype]==null)
LoadCar();
return (Car)_loadedcars[cartype];
}
public void LoadCar()
{
foreach(DictionaryEntry obj in _registeredcars)
{
Type type = (Type)obj.Value;
// could have used Activator class
ConstructorInfo info = type.GetConstructor(new Type[] {});
_loadedcars.Add(obj.Key,(Car)info.Invoke(new object[]{}));
}
}
}
The CarFactory class consists of two Hashtables registeredcars and loadedcars.
The Register method add the registerd cars to the hashtable. This is the full list of objects that you can create out of this factory. It is quite evident from the Register method that it adds a cartype and car in the Hashtable and performs the logical connection between the two.
The CreateCar method takes a cartype as argument and returns a car object. While creating a car it checks whether the asked-for car object is already loaded, it returns the object from the loadedcars Hashtable, otherwise it first loads it and then returns the object.
The LoadCar method does the main job in creating the asked-for car object and returning it. It loops in the registeredcars Hashtable to check whether the object is there , already registered in the Hashtable. It uses Reflection to create the type and adds it in the loadedcars Hashtable.
Now as the factory is implemented , it start using it …
static void Main(string[] args)
{
CarFactory factory = new CarFactory();
//registering cars
factory.Register(CarType.Ambassador,typeof(Ambassador));
factory.Register(CarType.Ford,typeof(Ford));
Car _car = factory.CreateCar(CarType.Ford);
Console.WriteLine(_car.GetType().ToString());
Console.ReadLine();
}
The cars that are needed are first registered, using a call to the Register method. Then we create the reuired car object by calling the Createcar() and passing the suitable cartype.
You can clearly see that any object that is registered ,can be created on runtime without the use of the earlier if-else… blocks.
Print | posted on Monday, May 21, 2007 8:58 PM