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
Simple factory vs Factory method
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 7: Now, integrate the FactoryMethod in the EmployeesController’s
Create method and replace the existing logic of simple factory method as stated
below.
Design Patterns tutorial for beginners
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
Simple factory vs Factory method
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.
CREATETABLE [dbo].[Employee](
[Id] INTIDENTITY (1, 1)NOTNULL,
[Name] VARCHAR (50)NOTNULL,
[JobDescription] VARCHAR (50)NOTNULL,
[Number] VARCHAR (50)NOTNULL,
[Department] VARCHAR (50)NOTNULL,
[HourlyPay] DECIMAL (18)NOTNULL,
[Bonus] DECIMAL (18)NOTNULL,
[EmployeeTypeID] INTNOTNULL,
[HouseAllowance] DECIMAL
(18)NULL,
[MedicalAllowance] DECIMAL (18)NULL,
PRIMARYKEYCLUSTERED ([Id] ASC),
CONSTRAINT
[FK_Employee_EmployeeType] FOREIGNKEY ([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
{
publicabstractclassBaseEmployeeFactory
{
protectedEmployee _emp;
public BaseEmployeeFactory(Employee emp)
{
_emp = emp;
}
publicEmployee ApplySalary()
{
IEmployeeManager manager = this.Create();
_emp.Bonus = manager.GetBonus();
_emp.HourlyPay = manager.GetPay();
return _emp;
}
publicabstractIEmployeeManager 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
{
publicclassContractEmployeeFactory : BaseEmployeeFactory
{
public ContractEmployeeFactory(Employee emp) : base(emp)
{
}
publicoverrideIEmployeeManager Create()
{
ContractEmployeeManager manager = newContractEmployeeManager();
_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
{
publicclassPermanentEmployeeFactory : BaseEmployeeFactory
{
public PermanentEmployeeFactory(Employee emp) : base(emp)
{
}
publicoverrideIEmployeeManager Create()
{
PermanentEmployeeManager manager = newPermanentEmployeeManager();
_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
{
publicclassEmployeeManagerFactory
{
publicBaseEmployeeFactory CreateFactory(Employee emp)
{
BaseEmployeeFactory returnValue = null;
if(emp.EmployeeTypeID ==1)
{
returnValue = newPermanentEmployeeFactory(emp);
}
elseif (emp.EmployeeTypeID ==2)
{
returnValue = newContractEmployeeFactory(emp);
}
return returnValue;
}
}
}
Step 7: Now, integrate the FactoryMethod in the EmployeesController’s
Create method and replace the existing logic of simple factory method as stated
below.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include
= "Id,Name,JobDescription,Number,Department,HourlyPay,Bonus,EmployeeTypeID")] Employee employee)
{
if (ModelState.IsValid)
{
BaseEmployeeFactory empFactory =
new EmployeeManagerFactory().CreateFactory(employee);
empFactory.ApplySalary();
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.EmployeeTypeID = new SelectList(db.Employee_Type, "Id",
"EmployeeType", employee.EmployeeTypeID);
return View(employee);
}
Step 8: Enhance the current Employee index view to add Medical Allowance and House Allowance columns.
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.
Factory Method Design Pattern exampleDesign Patterns tutorial for beginners
3 comments:
On step 7: Below is the corrected code. The output of "empFactory.ApplySalary()" is not being assigned to employee object.
Reply DeleteSince 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
Reply DeleteIt would be great if you can help share these free resources
[フレーム]