Factory Design Pattern
The factory design pattern is very simple. Several other patterns, like the abstract factory pattern, build off of it though, so it is a common base pattern. You use this pattern when one or more of the following are true:
1. A class can't anticipate the class of object it must create.
2. A class wants its subclasses to specify the objects it creates.
3. Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.[GOF108]
The class is easy to implement and consists of an identifier, either named constants or an enum and a switch statement. For our example we will be creating dog objects. As with any good OO design we start with an interface for our related objects. The IDog interface Code:
Problem
For example we have a scenario where based on user input we need to call particular class methods. I have a customer input screen. He enters his choice whether they want to buy a bike or a car. Normally we get input from the user and based on that will create an object in the client class and call those methods like below.
The factory design pattern is very simple. Several other patterns, like the abstract factory pattern, build off of it though, so it is a common base pattern. You use this pattern when one or more of the following are true:
1. A class can't anticipate the class of object it must create.
2. A class wants its subclasses to specify the objects it creates.
3. Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.[GOF108]
The class is easy to implement and consists of an identifier, either named constants or an enum and a switch statement. For our example we will be creating dog objects. As with any good OO design we start with an interface for our related objects. The IDog interface Code:
public interface IDog
{
void Bark();
void Scratch();
}
We just define a couple of simple methods for our dogs to do.
Now for the two actual concrete dog classes. We define a bulldog and poodle class:
Code:
public class CPoodle : IDog
{
public CPoodle()
{
Console.WriteLine("Creating Poodle");
}
public void Bark()
{
Console.WriteLine("Yip Yip");
}
public void Scratch()
{
Console.WriteLine("Scratch Scratch");
}
}
public class CBullDog : IDog
{
public CBullDog()
{
Console.WriteLine("Creating Bulldog");
}
public void Bark()
{
Console.WriteLine("Wooof Wooof");
}
public void Scratch()
{
Console.WriteLine("Scratch Slobber Scratch");
}
}
Now for our factory class. It’s static and contains one method to return the correct dog.
Code:
public class CDogFactory
{
public enum DogType
{
Poodle, Bulldog
}
static CDogFactory()
{
}
public static IDog CreateDog(DogType TypeOfDog)
{
switch (TypeOfDog)
{
case DogType.Bulldog:
return new CBullDog();
case DogType.Poodle:
return new CPoodle();
default:
throw new ArgumentException("Invalid Dog Type!");
}
}
}
We make the class static so we don’t need an instance of the class.
To test the class, I have created a simple function. Our test function just return the dogs and uses them. In a more real world app, the type of dog would have been determined by the user or through program logic.
Code:
IDog dog1; IDog dog2; dog1 = CDogFactory.CreateDog(CDogFactory.DogType.Bulldog); dog2 = CDogFactory.CreateDog(CDogFactory.DogType.Poodle); dog1.Bark(); dog1.Scratch(); dog2.Bark(); dog2.Scratch();
//
// customer enters their choice
//
If (choice == “Car”)
{
// call car class and it’s methods
Car c = new car();
c.buy();
}
If (choice == “bike”)
{
// call bike class and it’s methods
Bike b = new Bike();
b.buy()
}
...
In case in future if there is any other vehicle added then we need to change the client functionality.
The above client code depicts that there are classes Car, Bike, and a method Buy. There is no security at the client side.
Need to use the new keyword in client classes.
To avoid these problems Factory pattern is used.
Solution
Problem 1
Create a new interface to depict methods, for example, in our scenario, it is Buy(). Using this interface it will solve problems 1 and 2.
//
// Interface
//
public interface IChoice
{
string Buy();
}
A new class will be added and this class we will be called factory class. This class sits between the client class and the business class and based on user choice it will return the respective class object through the interface. It will solve problem 3.
//
// Factory Class
//
public class FactoryChoice
{
static public IChoice getChoiceObj(string cChoice)
{
IChoice objChoice=null;
if (cChoice.ToLower() == "car")
{
objChoice = new clsCar();
}
else if (cChoice.ToLower() == "bike")
{
objChoice = new clsBike();
}
else
{
objChoice = new InvalidChoice();
}
return objChoice;
}
}
//Business classes
//Car
public class clsBike:IChoice
{
#region IChoice Members
public string Buy()
{
return ("You choose Bike");
}
#endregion
}
//Bike
public class clsCar:IChoice
{
#region IChoice Members
public string Buy()
{
return ("You choose Car");
}
#endregion
}
From the client class call the factory class object and it will return the interface object. Through the interface object we will call the respective method.
//Client class IChoice objInvoice; objInvoice = FactoryClass.FactoryChoice.getChoiceObj(txtChoice.Text.Trim()); MessageBox.Show(objInvoice.Buy());In future if we need to add a new vehicle then there is no need to change the client class, simply return that object using the factory class. Advantages Suppose we want to add a decoupled structure and don’t want to disturb the client environment again and again, this pattern is very useful. The factory class will take all the burden of object creations.
No comments:
Post a Comment