Suggested Videos
Part 6 - Static Class vs Singleton - Text - Slides
Part 7 - Exception Logging using Singleton Design Pattern - Text - Slides
Part 8 - Factory Design Pattern Introduction - Text - Slides
In this tutorial we will learn
Recap Simple Factory
Factory Representation
From the above diagram, Factory representation block in the simple factory is replaced with Abstract Creator which further creates Concrete Creator A and Concrete Creator B Products providing another level of abstraction.
Factory Method Pattern Example
Business Requirement
Step 1: Add HouseAllowance and MedicalAllowance to the
existing Employee table.
Step 6: Create EmployeeManagerFactory class under
FactoryMethod folder and add new Method CreateFactory which returns
BaseEmployeeFactory.
Step 7: Now, integrate the FactoryMethod in the EmployeesController’s
Create method and replace the existing logic of simple factory method as stated
below.
Step 9: Run the application and notice that we have
achieved the business requirement by using Factory Method pattern. Below
illustrated diagram depicts how we have converted the simple to factory method
implementation.
Part 6 - Static Class vs Singleton - Text - Slides
Part 7 - Exception Logging using Singleton Design Pattern - Text - Slides
Part 8 - Factory Design Pattern Introduction - Text - Slides
In this tutorial we will learn
- Simple Factory
- Factory Method Pattern Implementation
Recap Simple Factory
- Simple factory abstracts the creation details of the product
- Simple factory refers to the newly created object through an interface
- Any new type creation is handled with a change of code in the factory class and not in the client code
public class EmployeeManagerFactory
{
public IEmployeeManager GetEmployeeManager(int employeeTypeID)
{
IEmployeeManager returnValue = null;
if (employeeTypeID == 1)
{
returnValue = new PermanentEmployeeManager();
}
else if
(employeeTypeID == 2)
{
returnValue = new ContractEmployeeManager();
}
return returnValue;
}
}
Factory Representation
From the above diagram, Factory representation block in the simple factory is replaced with Abstract Creator which further creates Concrete Creator A and Concrete Creator B Products providing another level of abstraction.
Factory Method Pattern Example
Business Requirement
- Differentiate employees as permanent and contract and segregate their pay scales as well as bonus based on their employee types. ( We have achieved this using simple factory in Part 8 of the Design Patterns tutorial)
- Calculate Permanent employee house rent allowance
- Calculate Contract employee medical allowance
Step 1: Add HouseAllowance and MedicalAllowance to the
existing Employee table.
CREATE TABLE [dbo].[Employee] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR (50) NOT NULL,
[JobDescription] VARCHAR (50) NOT NULL,
[Number] VARCHAR (50) NOT NULL,
[Department] VARCHAR (50) NOT NULL,
[HourlyPay] DECIMAL (18) NOT NULL,
[Bonus] DECIMAL (18) NOT NULL,
[EmployeeTypeID] INT NOT NULL,
[HouseAllowance] DECIMAL
(18) NULL,
[MedicalAllowance] DECIMAL (18) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT
[FK_Employee_EmployeeType] FOREIGN KEY ([EmployeeTypeID]) REFERENCES [dbo].[Employee_Type] ([Id]) );
Step 2: Open EmployeePortal.edmx under the Models folder of the solution and update the model from the database (Right click on the model designer and choose update from database option)
Step 3: Create FactoryMethod folder under existing Factory folder and add BaseEmployeeFactory class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Managers;
using Web.Models;
namespace Web.Factory.FactoryMethod
{
public abstract class BaseEmployeeFactory
{
protected Employee _emp;
public BaseEmployeeFactory(Employee emp)
{
_emp = emp;
}
public Employee ApplySalary()
{
IEmployeeManager manager = this.Create();
_emp.Bonus = manager.GetBonus();
_emp.HourlyPay = manager.GetPay();
return _emp;
}
public abstract IEmployeeManager Create();
}
}
Step 4: Create ContractEmployeeFactory class under FactoryMethod folder.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Managers;
using Web.Models;
namespace Web.Factory.FactoryMethod
{
public class ContractEmployeeFactory : BaseEmployeeFactory
{
public ContractEmployeeFactory(Employee emp) : base(emp)
{
}
public override IEmployeeManager Create()
{
ContractEmployeeManager manager = new ContractEmployeeManager();
_emp.MedicalAllowance =
manager.GetMedicalAllowance();
return manager;
}
}
}
Step 5: Create PermanentEmployeeFactory class under FactoryMethod folder.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Managers;
using Web.Models;
namespace Web.Factory.FactoryMethod
{
public class PermanentEmployeeFactory : BaseEmployeeFactory
{
public PermanentEmployeeFactory(Employee emp) : base(emp)
{
}
public override IEmployeeManager Create()
{
PermanentEmployeeManager manager = new PermanentEmployeeManager();
_emp.HouseAllowance =
manager.GetHouseAllowance();
return manager;
}
}
}
Step 6: Create EmployeeManagerFactory class under
FactoryMethod folder and add new Method CreateFactory which returns
BaseEmployeeFactory.
CreateFactory method is responsible to return base factory which is the base class of Permanent and Contract Factories.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Models;
namespace Web.Factory.FactoryMethod
{
public class EmployeeManagerFactory
{
public BaseEmployeeFactory CreateFactory(Employee emp)
{
BaseEmployeeFactory returnValue = null;
if(emp.EmployeeTypeID ==1)
{
returnValue = new PermanentEmployeeFactory(emp);
}
else if (emp.EmployeeTypeID ==2)
{
returnValue = new ContractEmployeeFactory(emp);
}
return returnValue;
}
}
}
On step 7: Below is the corrected code. The output of "empFactory.ApplySalary()" is not being assigned to employee object.
ReplyDeleteSince classes are reference types, I think there is no need to return the employee object from ApplySalary method.
DeletePlease correct me if I am wrong.
Missed the modification of PermanentEmployeeManager class GetHouseAllowance method in this code
ReplyDelete