Difference between revisions of "Simple Factory Pattern"
Line 142: | Line 142: | ||
EmployeeTypes _contractEmplyeeType = new EmployeeTypes | EmployeeTypes _contractEmplyeeType = new EmployeeTypes | ||
{ | { | ||
− | Id = | + | Id = 2, |
Name = "Contract Emplyee" | Name = "Contract Emplyee" | ||
}; | }; |
Latest revision as of 13:03, 23 February 2020
Simple Factory Pattern returns an instance of one of several possible classes depending on the type of data provided. It is quite common to return a common parent class and common methods, but each may perform a task differently or optimize for different data or behaviors.
The classes in Simple Factory Pattern will have the same parent class and methods but will perform the task differently dependent of the type of data supplied.
Let's take a look at the diagram to get a high-level view of how the Simple Factory Pattern works in C#.
In the diagram Manufacture is a base class, and classes Permanent Employee and Contract Employee are derived from it, the Manufacture class decides which of the subclasses to return, depending on the arguments provided.
The developer using the Manufacture class doesn’t really care which of the subclasses is returned, because each of them have the same methods but will have different implementations. How the factory class(Manufacture class) decides which one to return, is entirely up to what data is supplied.
Contents
Business Requirement Example
- We need two types of employee permanent and contract.
- Contract employee's Salary is 80000 and Bonus is 1000.
- Permanent employee's Salary is 50000 and Bonus is 5000.
Code Example
class EmployeeTypes { public int Id { get; set; } public string Name { get; set; } } class Employees { public string Name { get; set; } public EmployeeTypes EmployeeType { get; set; } public int Salary { get; set; } public int Bonus { get; set; } } class Program { static void Main(string[] args) { EmployeeTypes _contractEmplyeeType = new EmployeeTypes { Id = 2, Name = "Contract Emplyee" }; EmployeeTypes _permanentEmplyeeType = new EmployeeTypes { Id = 1, Name = "Permanent Emplyee" }; Employees _contractEmplyee = create("Jhon" , _contractEmplyeeType); Employees _permanentEmplyee = create("Mario", _permanentEmplyeeType); } static Employees create(string name,EmployeeTypes employeeType) { Employees _employee = new Employees(); if(employeeType.Id==1) { _employee.Salary = 50000; _employee.Bonus = 5000; } else if(employeeType.Id == 2) { _employee.Salary = 80000; _employee.Bonus = 1000; } _employee.EmployeeType = employeeType; return _employee; } }
Problem
The above solves our business requirement but we have some drawbacks..
- Tightly coupled business logic.
- Need more development and testing effort when any changes required because we need to update the create() function every-time.
- Violating Single Responsibility Principle as Main function/class is responsible for object creation and payment declaration.
- Violating Open-Closed-principle as we need to change the main function/class every time when we need a new type of employee.
Solution
Let's take a look at the below solution:
- We have decoupled Employee by using IEmployee interface.
- EmployeeFactory is responsible for object creation.
- Main function/class not responsible for object creation, so we don't have to change it when there is an update in salary/bonus or we have a new type of employee.
Code Example
public interface IEmployee { void setSalary(); void setBonus(); } class PermanentEmployee : IEmployee { public string Name { get; set; } public EmployeeTypes EmployeeType { get; set; } public int Salary { get; set; } public int Bonus { get; set; } public void setBonus() { Bonus = 5000; } public void setSalary() { Salary = 50000; } } class ContractEmployee : IEmployee { public string Name { get; set; } public EmployeeTypes EmployeeType { get; set; } public int Salary { get; set; } public int Bonus { get; set; } public void setBonus() { Bonus = 1000; } public void setSalary() { Salary = 80000; } } class EmployeeFactory { public IEmployee GetEmployee(string name, EmployeeTypes employeeType) { IEmployee _employee= null; if (employeeType.Id == 1) { _employee = new PermanentEmployee() { Name = name }; } else if (employeeType.Id == 2) { _employee = new ContractEmployee() { Name = name }; } return _employee; } } class EmployeeTypes { public int Id { get; set; } public string Name { get; set; } } class Program { static void Main(string[] args) { EmployeeTypes _contractEmplyeeType = new EmployeeTypes { Id = 2, Name = "Contract Emplyee" }; EmployeeTypes _permanentEmplyeeType = new EmployeeTypes { Id = 1, Name = "Permanent Emplyee" }; EmployeeFactory employeeFactory = new EmployeeFactory(); IEmployee _contractEmplyee = employeeFactory.GetEmployee("Jhon" , _contractEmplyeeType); _contractEmplyee.setBonus(); _contractEmplyee.setSalary(); IEmployee _permanentEmplyee = employeeFactory.GetEmployee("Mario", _permanentEmplyeeType); _permanentEmplyee.setBonus(); _permanentEmplyee.setSalary(); } }
Advantage of Simple Factory Pattern
This follows the Open-Closed-principle: Our Employee class is closed, as we have a fixed set of Employee, which we hire, but we are open for new Employees.
Further: Each new Employee have their set of functions. The Permanent Employee doesn't care what/how to do a Contract Employee (Single Responsibility Principle).
Last but not least, we decoupled different Employee types from the Main function. The main function needs only to know how to handle.