Factory Design Pattern is a type of Creational Design Pattern.
Creational Design Pattern deals with creation of object such that they can be decoupled from their implementing system. Using this design pattern it is very easy to decide which objects needs to be created for a given scenario.
Factory Pattern returns an instance of one of several possible classes, depending on the data
Factory pattern accepts a parameter depending of this parameter it returns one of the several possible classes. These possible classes have same parent class and method but each has different implementation.
Real time reason to implement Factory Pattern and why not directly create objects with constructor calls ? ?
For simple code I also would suggest not yo use factory. Sometimes it is better to not to use any design pattern as design patterns introduces some level of complexity in the code. But for large applications where many developers are working any many code changes are expected, it is recommended to use factory. Still, I haven't answered the main question Why Factory ? Don't worry...I will answer in a while..It is very important design pattern and I don't want you to learn in a hurry.
Let me try to answer you some potential reasons to use factory:
With constructor approach to create an object, at some point of time the constructor may require different number of parameters which will cause client to change code everywhere ( tight coupling ).
Separation of concern : Business classes needs to use complex objects but they need not to know how they created before using it.
Another design related reason can be Open/Close Principle Let's take a simple case of database, If the back-end being used in your application is SQL Server and in nearest future you need to change it to Oracle you would need to modify your code.
Another obvious reason is you may not know in advance which concrete class needs to be created.
I have seen the below kind of code at my places, is this a Factory ? Nooo.... This is not a Factory.
Of course based on some creational logic it will return the int value but let's go back to Factory Definition, Factory always returns abstraction i.e. an interface or an abstract class.
Program class implementation :
class Program
{
static void Main(string[] args)
{
string vehicleName = args[0];
IVehicle vehicle = GetVehicle(vehicleName);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
private static IVehicle GetVehicle(string vehichleName)
{
switch (vehichleName)
{
case "Car":
return new Car();
case "Truck":
return new Truck();
case "Bus":
return new Bus();
case "Tempo":
return new Tempo();
default:
throw new Exception("No such vehicle found");
}
}
}
:
Perfect!! expected output...Now Is this a Factory ?
Let me answer this in a while. Consider we have some another vehicle type i.e. Bike
public class Bike: IVehicle
{
}
We have to extend switch case , Oh! again it is a violation of Open/Closed principle. Also Program.cs should be aware of new implementation of IVehicle as this is responsible to find the correct concrete type, ideally Program.cs should just understand IVehicle interface. Before defining the solution of these issues let me answer you the question Is this a Factory ? Yes, This is a Factory or say Simple Factory with some disadvantages I already discussed.
Potential Solution :
Factory Method : lets a class defer instantiation to sub classes.
Just add some code and modify Program class.
Add interface for Factory and create Factory for each Type
public interface IVehicleFactory
{
IVehicle CreateVehicle();
}
public class CarFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Car();
}
}
public class BusFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Bus();
}
}
public class TruckFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Truck();
}
}
public class TempoFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Tempo();
}
}
Modify Program class:
class Program
{
static void Main(string[] args)
{
string vehichleName = args[0];
if(vehicleName.Equals("Car")){
IVehicleFactory factory = new CarFactory();
var car=factory.CreateVehicle();
car.Start();
car.Stop();
}
}
}
That's it!! Factory Method is implemented
You want to add anther type, Bike ? Add a separate Factory for it and you are done, no chance in factory is required. Also, Program class calls CarFactory (Factory Method) without knowing how and what actual type of the object was created.
Some more on Factory Design Pattern - Different Flavor and usage
Factory with Reflection...
Just Keep IVehicle Interface and Concrete Classes, remove all other code
Below is the modified Factory class
public class VehicleFactory
{
Dictionary<string, Type> vehicles;
public VehicleFactory()
{
LoadTypesICanReturn();
}
public IVehicle CreateInstance(string vehicleName)
{
Type t = GetTypeToCreate(vehicleName);
if (t == null)
throw new Exception("Bad Type");
else
return Activator.CreateInstance(t) as IVehicle;
}
private Type GetTypeToCreate(string vehicleName)
{
foreach (var vehicle in vehicles)
{
if (vehicle.Key.Contains(vehicleName))
{
return vehicles[vehicle.Key];
}
}
return null;
}
private void LoadTypesICanReturn()
{
vehicles = new Dictionary<string, Type>();
Type[] typeInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typeInThisAssembly)
{
if (type.GetInterface(typeof(IVehicle).ToString())!=null)
{
vehicles.Add(type.Name.ToLower(), type);
}
}
}
}
Accordingly Program class will get changed
class Program
{
static void Main(string[] args)
{
string vehicleName = args[0];
VehicleFactory factory = new VehicleFactory();
IVehicle vehicle= factory.CreateInstance(vehicleName);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
}
Note: We are converting args[0] value in toLower()
With this solution also, we don't need to extend Factory class, any new type would be taken care by reflection.Program.cs is not any longer aware of the concrete Vehicle types.
In the above 2 solutions i.e Factory Method and Factory with Reflection the problem we can say is Caller is aware of which factory is getting called which is introducing unnecessary coupling between calling client and concrete class. The Type of Factory should be hidden.
Solution with abstract Factory:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Vehicles
{
class Program
{
static void Main(string[] args)
{
string description = args[0];
IVehicleFactory vehicleFactory = LoadFactory();
IVehicle vehicle= vehicleFactory.CreateInstance(description);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
private static IVehicleFactory LoadFactory()
{
string factoryName = Properties.Settings.Default.DefaultVehicleFactory;
return Assembly.GetExecutingAssembly().CreateInstance(factoryName) as IVehicleFactory;
}
}
public interface IVehicle
{
string VehicleName { get; }
void Start();
void Stop();
}
public class Car : IVehicle
{
public string VehicleName
{
get { return "Car"; }
}
public void Start()
{
Console.WriteLine("I am a car and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Car and I am going to stop");
}
}
public class Truck : IVehicle
{
public string VehicleName
{
get { return "Truck"; }
}
public void Start()
{
Console.WriteLine("I am a Truck and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Truck and I am going to stop");
}
}
public class Bus : IVehicle
{
public string VehicleName
{
get { return "Bus"; }
}
public void Start()
{
Console.WriteLine("I am a Bus and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Bus and I am going to stop");
}
}
public class Tempo : IVehicle
{
public string VehicleName
{
get { return "Tempo"; }
}
public void Start()
{
Console.WriteLine("I am a Tempo and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Tempo and I am going to stop");
}
}
public class VehicleFactory : IVehicleFactory
{
Dictionary<string, Type> vehicles;
public VehicleFactory()
{
LoadTypesICanReturn();
}
public IVehicle CreateInstance(string vehicleName)
{
Type t = GetTypeToCreate(vehicleName);
if (t == null)
throw new Exception("Bad Type");
else
return Activator.CreateInstance(t) as IVehicle;
}
private Type GetTypeToCreate(string vehicleName)
{
foreach (var vehicle in vehicles)
{
if (vehicle.Key.Contains(vehicleName))
{
return vehicles[vehicle.Key];
}
}
return null;
}
private void LoadTypesICanReturn()
{
vehicles = new Dictionary<string, Type>();
Type[] typeInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typeInThisAssembly)
{
if (type.GetInterface(typeof(IVehicle).ToString())!=null)
{
vehicles.Add(type.Name.ToLower(), type);
}
}
}
}
public interface IVehicleFactory
{
IVehicle CreateInstance(string description);
}
}
Creational Design Pattern deals with creation of object such that they can be decoupled from their implementing system. Using this design pattern it is very easy to decide which objects needs to be created for a given scenario.
Factory Pattern returns an instance of one of several possible classes, depending on the data
Factory pattern accepts a parameter depending of this parameter it returns one of the several possible classes. These possible classes have same parent class and method but each has different implementation.
Real time reason to implement Factory Pattern and why not directly create objects with constructor calls ? ?
For simple code I also would suggest not yo use factory. Sometimes it is better to not to use any design pattern as design patterns introduces some level of complexity in the code. But for large applications where many developers are working any many code changes are expected, it is recommended to use factory. Still, I haven't answered the main question Why Factory ? Don't worry...I will answer in a while..It is very important design pattern and I don't want you to learn in a hurry.
Let me try to answer you some potential reasons to use factory:
With constructor approach to create an object, at some point of time the constructor may require different number of parameters which will cause client to change code everywhere ( tight coupling ).
Separation of concern : Business classes needs to use complex objects but they need not to know how they created before using it.
Another design related reason can be Open/Close Principle Let's take a simple case of database, If the back-end being used in your application is SQL Server and in nearest future you need to change it to Oracle you would need to modify your code.
Another obvious reason is you may not know in advance which concrete class needs to be created.
I have seen the below kind of code at my places, is this a Factory ? Nooo.... This is not a Factory.
Of course based on some creational logic it will return the int value but let's go back to Factory Definition, Factory always returns abstraction i.e. an interface or an abstract class.
int bonus= BonusFactory.CalculateEmployeeBonus(input employeeBonusRequest
);
To be continued ......., I have doctor's appointment,
I ll try to finish implementation by tonight.
I came back ..ll resume writing this blog, Let's do some Lab session and understand the Factory .
Take Vehicles example, all the vehicles has Start and Stop Operation.
public
interface
IVehicle
{
string
VehicleName {
get
; }
void
Start();
void
Stop();
}
Some Vehicles:
public class Car : IVehicle
{
public
string
VehicleName
{
get
{
return
"Car"
; }
}
public
void
Start()
{
Console.WriteLine(
"I am a car and I am going to start."
);
}
public
void
Stop()
{
Console.WriteLine(
"I am a Car and I am going to stop"
);
}
}
public class Truck: IVehicle
{
public
string
VehicleName
{
get
{
return
"Truck"
; }
}
public
void
Start()
{
Console.WriteLine(
"I am a Truck and I am going to start."
);
}
public
void
Stop()
{
Console.WriteLine(
"I am a Truck and I am going to stop"
);
}
}
public class Bus : IVehicle
{
public string VehicleName
{
get { return "Bus"; }
}
public void Start()
{
Console.WriteLine("I am a Bus and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Bus and I am going to stop");
}
}
public class Tempo : IVehicle
{
public string VehicleName
{
get { return "Tempo"; }
}
public void Start()
{
Console.WriteLine("I am a Tempo and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Tempo and I am going to stop");
}
}
class Program
{
static void Main(string[] args)
{
string vehicleName = args[0];
IVehicle vehicle = GetVehicle(vehicleName);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
private static IVehicle GetVehicle(string vehichleName)
{
switch (vehichleName)
{
case "Car":
return new Car();
case "Truck":
return new Truck();
case "Bus":
return new Bus();
case "Tempo":
return new Tempo();
default:
throw new Exception("No such vehicle found");
}
}
}
Output:
Perfect!! expected output...Now Is this a Factory ?
Let me answer this in a while. Consider we have some another vehicle type i.e. Bike
public class Bike: IVehicle
{
public
string
VehicleName
{
get
{
return
"Bike"
; }
}
public
void
Start()
{
Console.WriteLine(
"I am a Bike and I am going to start."
);
}
public
void
Stop()
{
Console.WriteLine(
"I am a Bike and I am going to stop"
);
}
We have to extend switch case , Oh! again it is a violation of Open/Closed principle. Also Program.cs should be aware of new implementation of IVehicle as this is responsible to find the correct concrete type, ideally Program.cs should just understand IVehicle interface. Before defining the solution of these issues let me answer you the question Is this a Factory ? Yes, This is a Factory or say Simple Factory with some disadvantages I already discussed.
Potential Solution :
Factory Method : lets a class defer instantiation to sub classes.
Just add some code and modify Program class.
Add interface for Factory and create Factory for each Type
public interface IVehicleFactory
{
IVehicle CreateVehicle();
}
public class CarFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Car();
}
}
public class BusFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Bus();
}
}
public class TruckFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Truck();
}
}
public class TempoFactory : IVehicleFactory
{
public IVehicle CreateVehicle()
{
return new Tempo();
}
}
Modify Program class:
class Program
{
static void Main(string[] args)
{
string vehichleName = args[0];
if(vehicleName.Equals("Car")){
IVehicleFactory factory = new CarFactory();
var car=factory.CreateVehicle();
car.Start();
car.Stop();
}
}
}
That's it!! Factory Method is implemented
You want to add anther type, Bike ? Add a separate Factory for it and you are done, no chance in factory is required. Also, Program class calls CarFactory (Factory Method) without knowing how and what actual type of the object was created.
Some more on Factory Design Pattern - Different Flavor and usage
Factory with Reflection...
Just Keep IVehicle Interface and Concrete Classes, remove all other code
Below is the modified Factory class
public class VehicleFactory
{
Dictionary<string, Type> vehicles;
public VehicleFactory()
{
LoadTypesICanReturn();
}
public IVehicle CreateInstance(string vehicleName)
{
Type t = GetTypeToCreate(vehicleName);
if (t == null)
throw new Exception("Bad Type");
else
return Activator.CreateInstance(t) as IVehicle;
}
private Type GetTypeToCreate(string vehicleName)
{
foreach (var vehicle in vehicles)
{
if (vehicle.Key.Contains(vehicleName))
{
return vehicles[vehicle.Key];
}
}
return null;
}
private void LoadTypesICanReturn()
{
vehicles = new Dictionary<string, Type>();
Type[] typeInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typeInThisAssembly)
{
if (type.GetInterface(typeof(IVehicle).ToString())!=null)
{
vehicles.Add(type.Name.ToLower(), type);
}
}
}
}
Accordingly Program class will get changed
class Program
{
static void Main(string[] args)
{
string vehicleName = args[0];
VehicleFactory factory = new VehicleFactory();
IVehicle vehicle= factory.CreateInstance(vehicleName);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
}
Note: We are converting args[0] value in toLower()
With this solution also, we don't need to extend Factory class, any new type would be taken care by reflection.Program.cs is not any longer aware of the concrete Vehicle types.
In the above 2 solutions i.e Factory Method and Factory with Reflection the problem we can say is Caller is aware of which factory is getting called which is introducing unnecessary coupling between calling client and concrete class. The Type of Factory should be hidden.
Solution with abstract Factory:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Vehicles
{
class Program
{
static void Main(string[] args)
{
string description = args[0];
IVehicleFactory vehicleFactory = LoadFactory();
IVehicle vehicle= vehicleFactory.CreateInstance(description);
vehicle.Start();
vehicle.Stop();
Console.ReadKey();
}
private static IVehicleFactory LoadFactory()
{
string factoryName = Properties.Settings.Default.DefaultVehicleFactory;
return Assembly.GetExecutingAssembly().CreateInstance(factoryName) as IVehicleFactory;
}
}
public interface IVehicle
{
string VehicleName { get; }
void Start();
void Stop();
}
public class Car : IVehicle
{
public string VehicleName
{
get { return "Car"; }
}
public void Start()
{
Console.WriteLine("I am a car and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Car and I am going to stop");
}
}
public class Truck : IVehicle
{
public string VehicleName
{
get { return "Truck"; }
}
public void Start()
{
Console.WriteLine("I am a Truck and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Truck and I am going to stop");
}
}
public class Bus : IVehicle
{
public string VehicleName
{
get { return "Bus"; }
}
public void Start()
{
Console.WriteLine("I am a Bus and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Bus and I am going to stop");
}
}
public class Tempo : IVehicle
{
public string VehicleName
{
get { return "Tempo"; }
}
public void Start()
{
Console.WriteLine("I am a Tempo and I am going to start.");
}
public void Stop()
{
Console.WriteLine("I am a Tempo and I am going to stop");
}
}
public class VehicleFactory : IVehicleFactory
{
Dictionary<string, Type> vehicles;
public VehicleFactory()
{
LoadTypesICanReturn();
}
public IVehicle CreateInstance(string vehicleName)
{
Type t = GetTypeToCreate(vehicleName);
if (t == null)
throw new Exception("Bad Type");
else
return Activator.CreateInstance(t) as IVehicle;
}
private Type GetTypeToCreate(string vehicleName)
{
foreach (var vehicle in vehicles)
{
if (vehicle.Key.Contains(vehicleName))
{
return vehicles[vehicle.Key];
}
}
return null;
}
private void LoadTypesICanReturn()
{
vehicles = new Dictionary<string, Type>();
Type[] typeInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typeInThisAssembly)
{
if (type.GetInterface(typeof(IVehicle).ToString())!=null)
{
vehicles.Add(type.Name.ToLower(), type);
}
}
}
}
public interface IVehicleFactory
{
IVehicle CreateInstance(string description);
}
}
Here I have just defined the basic idea of Abstract Factory, For more on Abstract Factory I insist you to read my another article on Abstract Factory
Comments
Post a Comment