To understand Abstract Factory and Factory Method design patterns, we need to understand Factory in real terms.
What is Factory?
In general terms, Factory is a manufacturing unit which does processing to deliver specific output.
Example – Fiat Automobiles which develops most efficient engines in the world.
What is the relation between real term Factory and Factory best practices in Software Development?
Factory in Real Terms – Factory is being setup to create the specific output based on specific input. As well factory has specific algorithm using which it develops the specific output. The same factory cannot use to achieve different purposes.
Conclusion of Factory in Real Terms - As per the statement, it is clear that factory is stringent and has specific demand as well specific behaviour.
Factory Best Practice in Software Development –Factory in software design pattern is stringent and used only to create instances of the specific class. That is why Factory pattern is listed under Creation Pattern.
What problem factory pattern solves? - Factory pattern helps to solve the dependency problem.
Example – You have a requirement to develop Employee module for an IT organisation. The Employee module consists of employee details and address details.
The simplest and classic structural implementation would be
Public class Employee
{
Public Emplyee() { }
Public string EmployeeId()
{
Return “ID1”;
}
Public string AddressLine1()
{
Return “AddressLine1”;
}
Public string AddressLine2()
{
Return “AddressLine2”;
}
Public string State()
{
Return “State”;
}
}
Conclusion on this implementation – Employee class consists of address details. If business requirement is restricted to employee id details with employee residency details, then this implementation is sufficient and will be faster.
Problem introduced using above example – Is employee details limited to employee id only? Employee details may also consists of Plant Address where Employee is working. The Address details which are common for employee residency and employee plant location generates code redundancy. As well introduces code dependency that is, any changes later identified for Address, requires modification in Employee Class and retesting.
Solution to the problem – Separation of Address class and object referring in Employee Class using Factory.
The simplest object oriented implementation using Factory would be
Public class Address
{
Public Address () { }
Public string AddressLine1()
{
Return “AddressLine1”;
}
Public string AddressLine2()
{
Return “AddressLine2”;
}
Public string State()
{
Return “State”;
}
}
Public class Employee
{
Public Emplyee() { }
Public string EmployeeId()
{
Return “ID1”;
}
Public Address GetPlantAddress()
{
Address clsAddress = new Address();
Return clsAddress();
}
Public Address GetResidencyAddress()
{
Address clsAddress = new Address();
Return clsAddress();
}
}
How to implement Factory method? – Many a times the implementation is done where the caller knows the child class to call. This type of implementation comes under Factory Method.
Example – As per the Factory example GetPlantAddress() and GetResidencyAddress() methods knows they are calling Address Class internally to get the respective details. There is no separate implementation for PlantAddress and ResidencyAddress. Such implementation are the candidates for Factory Method.
What is Abstract Factory? - Abstract Factory is an abstraction over factory method.
What is the difference between Factory Method and Abstract Factory? - In Factory Method, Caller knows the child classes to call where as in Abstract Factory caller does not know child classes to call. Abstraction plays important roll to hide calling implementation from caller and actual object assigning is done at run time.
Abstract Factory performs Inversion of control. That is Caller does not depends on child classes. Child classes depends on abstraction and abstraction does not depends on child classes.
The simplest object oriented implementation using Abstract Factory would be
Public class Address
{
Public Address (string addressType)
{
If (addressType == “Residency”)
{
Return new ResidencyAddress();
}
else (addressType == “Plant”)
{
Return new PlantAddress ();
}
}
Public virtual string AddressLine1()
{
Return “AddressLine1”;
}
Public virtual string AddressLine2()
{
Return “AddressLine2”;
}
Public virtual string State()
{
Return “State”;
}
}
Public class PlantAddress : Address
{
Public PlantAddress () { }
Public override string AddressLine1()
{
Return “AddressLine1”;
}
Public override string AddressLine2()
{
Return “AddressLine2”;
}
Public override string State()
{
Return “State”;
}
}
Public class ResidencyAddress : Address
{
Public PlantAddress () { }
Public override string AddressLine1()
{
Return “AddressLine1”;
}
Public override string AddressLine2()
{
Return “AddressLine2”;
}
Public override string State()
{
Return “State”;
}
}
Public class Employee
{
Public Emplyee() { }
Public string EmployeeId()
{
Return “ID1”;
}
Public Address GetAddress(string addressType)
{
Address clsAddress = new Address(addressType);
Return clsAddress();
}
}