Skip to content

Commit e1cb903

Browse files
committed
Added Builder Pattern
1 parent 84a5e89 commit e1cb903

13 files changed

Lines changed: 267 additions & 3 deletions
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace SoftwarePatterns.Core.Builder
2+
{
3+
public enum Band
4+
{
5+
Entry,
6+
Lower,
7+
Middle,
8+
Higher,
9+
Executive
10+
}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace SoftwarePatterns.Core.Builder
2+
{
3+
public enum Department
4+
{
5+
IT,
6+
HR,
7+
Accounting,
8+
ServiceDesk
9+
}
10+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SoftwarePatterns.Core.Builder
5+
{
6+
/// <summary>
7+
/// This class is created to solve the problem of the employee with the large constructor by making all fields public properties.
8+
/// However the issues with this is that we can no longer control the order or process of construction this is solved using director and builders
9+
/// The employee object is now only concerned with data not process or logic around how it is made
10+
/// </summary>
11+
public class Employee
12+
{
13+
public string Name { get; set; }
14+
public string Email { get; set; }
15+
public string Phone { get; set; }
16+
public Department Department { get; set; }
17+
public Band Band { get; set; }
18+
public bool IsFullTime { get; set; }
19+
public List<string> Certifications { get; set; }
20+
21+
public void Display()
22+
{
23+
Console.WriteLine("Employee Details");
24+
Console.WriteLine("Name: {0}", Name);
25+
Console.WriteLine("Email: {0}", Email);
26+
Console.WriteLine("Phone: {0}", Phone);
27+
Console.WriteLine("Department: {0}", Department);
28+
Console.WriteLine("Band: {0}", Band);
29+
Console.WriteLine("FullTime: {0}", IsFullTime);
30+
31+
Console.WriteLine("Certifications:");
32+
Certifications.ForEach(s => Console.WriteLine("{0}",s));
33+
Console.WriteLine();
34+
}
35+
}
36+
37+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace SoftwarePatterns.Core.Builder
2+
{
3+
/// <summary>
4+
/// Each employee builder is expected to know what is required at each stage of the process for its given implementation type
5+
/// </summary>
6+
public abstract class EmployeeBuilder
7+
{
8+
protected Employee employee;
9+
10+
public abstract void AddCertifications();
11+
public abstract void AddHrDetails();
12+
public abstract void AddPersonalDetails();
13+
public abstract void EnterDepartment();
14+
15+
public virtual void CreateNewSandwitch()
16+
{
17+
employee = new Employee();
18+
}
19+
20+
public Employee GetEmployee()
21+
{
22+
return employee;
23+
}
24+
}
25+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SoftwarePatterns.Core.Builder
5+
{
6+
/// <summary>
7+
/// Class issues that our constructor grows and grows and becomes difficult to work with
8+
/// </summary>
9+
public class EmployeeConstructorTooBig
10+
{
11+
private readonly string name;
12+
private readonly string email;
13+
private readonly string phone;
14+
private readonly Department department;
15+
private readonly Band band;
16+
private readonly bool isFullTime;
17+
private readonly List<string> certifications;
18+
19+
public EmployeeConstructorTooBig(string name,string email, string phone, Department department, Band band, bool isFullTime, List<string> certifications)
20+
{
21+
this.name = name;
22+
this.email = email;
23+
this.phone = phone;
24+
this.department = department;
25+
this.band = band;
26+
this.isFullTime = isFullTime;
27+
this.certifications = certifications;
28+
}
29+
30+
public void Display()
31+
{
32+
Console.WriteLine("Employee Details");
33+
Console.WriteLine("Name: {0}", name);
34+
Console.WriteLine("Email: {0}", email);
35+
Console.WriteLine("Phone: {0}", phone);
36+
Console.WriteLine("Department: {0}", department);
37+
Console.WriteLine("Band: {0}", band);
38+
Console.WriteLine("FullTime: {0}", isFullTime);
39+
40+
Console.WriteLine("Certifications:");
41+
certifications.ForEach(s => Console.WriteLine("{0}",s));
42+
Console.WriteLine();
43+
}
44+
}
45+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace SoftwarePatterns.Core.Builder
2+
{
3+
/// <summary>
4+
/// The employee director encapsulates the process of construction. It does not know anything about the data it only knows about order of operation.
5+
/// </summary>
6+
public class EmployeeDirector
7+
{
8+
private readonly EmployeeBuilder builder;
9+
10+
public EmployeeDirector(EmployeeBuilder builder)
11+
{
12+
this.builder = builder;
13+
}
14+
15+
public Employee CreateEmployee()
16+
{
17+
builder.CreateNewSandwitch();
18+
builder.AddPersonalDetails();
19+
builder.AddCertifications();
20+
builder.EnterDepartment();
21+
builder.AddHrDetails();
22+
23+
return builder.GetEmployee();
24+
}
25+
}
26+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
The builder pattern is used when object construction becomes complex.
2+
3+
It deals with the issue of:
4+
1. Too many parameters
5+
2. When constructor parameters become order dependent
6+
3. Construct different objects (we need to separate data and logic)
7+
8+
The pattern separates the construction of a complex object form its representation so the same construction process can create different representations.
9+
10+
11+
Examples:
12+
In our example we have a class the employee which constructor is getting to big. We refractor this so that we expose its data as public properties. This now mean we have no control over how our object is built.
13+
So give us this control back we produce a Employee director this class knows what is the process for building an object but should not care about the data required to generate any concrete instance of the employee class.
14+
The maker takes a employee builder this is an abstract class the we need to implement for any given employee type. These clases are concerned with what data is needed for their given type but not the process logic.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Collections.Generic;
2+
3+
namespace SoftwarePatterns.Core.Builder
4+
{
5+
public class ServiceDeskEmployeeBuilder : EmployeeBuilder
6+
{
7+
public override void AddCertifications()
8+
{
9+
employee.Certifications = new List<string>();
10+
}
11+
12+
public override void AddHrDetails()
13+
{
14+
employee.Band = Band.Entry;
15+
employee.IsFullTime = false;
16+
}
17+
18+
public override void AddPersonalDetails()
19+
{
20+
employee.Name = "Name";
21+
employee.Email = "Email";
22+
employee.Phone = "048915646131";
23+
}
24+
25+
public override void EnterDepartment()
26+
{
27+
employee.Department = Department.ServiceDesk;
28+
}
29+
}
30+
}

src/SoftwarePatterns.Core/SoftwarePatterns.Core.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,20 @@
5252
<Compile Include="Bridge\Manuscript.cs" />
5353
<Compile Include="Bridge\Paper.cs" />
5454
<Compile Include="Bridge\StandardFormatter.cs" />
55+
<Compile Include="Builder\Band.cs" />
56+
<Compile Include="Builder\Department.cs" />
57+
<Compile Include="Builder\EmployeeBuilder.cs" />
58+
<Compile Include="Builder\EmployeeConstructorTooBig.cs" />
59+
<Compile Include="Builder\Employee.cs" />
60+
<Compile Include="Builder\EmployeeDirector.cs" />
61+
<Compile Include="Builder\ServiceDeskEmployeeBuilder.cs" />
5562
<Compile Include="Extensions.cs" />
5663
<Compile Include="Properties\AssemblyInfo.cs" />
5764
</ItemGroup>
5865
<ItemGroup>
5966
<Content Include="Adapter\ReadMe.txt" />
6067
<Content Include="Bridge\ReadMe.txt" />
68+
<Content Include="Builder\ReadMe.txt" />
6169
</ItemGroup>
6270
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
6371
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Ploeh.AutoFixture;
2+
using SoftwarePatterns.Core.Builder;
3+
using Xunit;
4+
5+
namespace SoftwarePatterns.Tests.Builder
6+
{
7+
public class ServiceDeskEmployeeBuilderTests
8+
{
9+
public class CreateEmployeeMethod
10+
{
11+
[Fact]
12+
public void ShouldAddEmployeeToServiceDeskDepartment()
13+
{
14+
var fixture = new Fixture();
15+
var builder = fixture.Create<ServiceDeskEmployeeBuilder>();
16+
var director = new EmployeeDirector(builder);
17+
18+
var employee = director.CreateEmployee();
19+
20+
Assert.Equal(Department.ServiceDesk, employee.Department);
21+
}
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)