Suggested Videos
Part 9 - Factory Method Design Pattern - Text - Slides
Part 10 - Abstract Factory Design Pattern - Text - Slides
Part 11 - Builder Desing Pattern Implementation - Text - Slides
In this video we will learn Implementing Builder design pattern
Business Requirement : Provide an option to choose and build configuration of the system which is allocated to the employees. The configuration options that user can choose are RAM, HDD, USB Mouse etc. Choose the system configurations based on the computer type that we need to build. For example, A laptop users can choose touch screen and the desktop users can configure keyboard and mouse.
Here are the steps to implement builder design pattern
Step 1 : Add ISystemBuilder interface
Part 9 - Factory Method Design Pattern - Text - Slides
Part 10 - Abstract Factory Design Pattern - Text - Slides
Part 11 - Builder Desing Pattern Implementation - Text - Slides
In this video we will learn Implementing Builder design pattern
Business Requirement : Provide an option to choose and build configuration of the system which is allocated to the employees. The configuration options that user can choose are RAM, HDD, USB Mouse etc. Choose the system configurations based on the computer type that we need to build. For example, A laptop users can choose touch screen and the desktop users can configure keyboard and mouse.
Here are the steps to implement builder design pattern
Step 1 : Add ISystemBuilder interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Web.Builder.IBuilder
{
public interface ISystemBuilder
{
void AddMemory(string memory);
void AddDrive(string size);
void AddKeyBoard(string type);
void AddMouse(string type);
void AddTouchScreen(string enabled);
ComputerSystem GetSystem();
}
}
Step 2 : Add desktop builder and inherit ISystemBuilder interface and implement the Interface methods and assign the properties to the computer system that is being built.
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Builder.IBuilder;
namespace
Web.Builder.ConcreteBuilder
{
public class DesktopBuilder : ISystemBuilder
{
ComputerSystem desktop
= new ComputerSystem();
public void AddDrive(string size)
{
desktop.HDDSize
= size;
}
public void AddKeyBoard(string type)
{
desktop.KeyBoard
= type;
}
public void AddMemory(string memory)
{
desktop.RAM =
memory;
}
public void AddMouse(string type)
{
desktop.Mouse =
type;
}
public void
AddTouchScreen(string enabled)
{
return;
}
public ComputerSystem
GetSystem()
{
return desktop;
}
}
}
Step 3 : Add laptop builder and inherit ISystemBuilder interface and implement the Interface methods and assign the properties to the computer system that is being built.
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Builder.IBuilder;
namespace
Web.Builder.ConcreteBuilder
{
public class LaptopBuilder : ISystemBuilder
{
ComputerSystem laptop =
new ComputerSystem();
public void AddDrive(string size)
{
laptop.HDDSize =
size;
}
public void AddKeyBoard(string type)
{
return;
}
public void AddMemory(string memory)
{
laptop.RAM =
memory;
}
public void AddMouse(string type)
{
return;
}
public void
AddTouchScreen(string enabled)
{
laptop.TouchScreen = enabled;
}
public ComputerSystem
GetSystem()
{
return laptop;
}
}
}
Step 4 : Add configuration builder class which is the director to build the system
using System;
using
System.Collections.Generic;
using
System.Collections.Specialized;
using System.Linq;
using System.Web;
using Web.Builder.IBuilder;
namespace Web.Builder.Director
{
public class ConfigurationBuilder
{
public void BuildSystem(ISystemBuilder
systembuilder
, NameValueCollection collection)
{
systembuilder.AddDrive(collection["Drive"]);
systembuilder.AddMemory(collection["RAM"]);
systembuilder.AddMouse(collection["Mouse"]);
systembuilder.AddKeyBoard(collection["Keyboard"]);
systembuilder.AddTouchScreen(collection["TouchScreen"]);
}
}
}
Step 5 : Remove the constructor with the parameters and change the private properties to public so that they can be initialized from the concrete builder classes
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace Web
{
public class ComputerSystem
{
public string RAM { get; set; }
public string HDDSize { get; set; }
public string KeyBoard { get; set; }
public string Mouse { get; set; }
public string TouchScreen { get; set; }
public
ComputerSystem()
{
}
}
}
Step 6 : Enhance the BuildSystem action method from the previous session by returning desktop and laptop views based on the system allocated to the employees
[HttpGet]
public ActionResult BuildSystem(int? employeeID)
{
Employee employee = db.Employees.Find(employeeID);
if
(employee.ComputerDetails.Contains("Laptop"))
return View("BuildLaptop", employeeID);
else
return View("BuildDesktop", employeeID);
}
}
Step 7 : Add Build laptop action method as shown below
[HttpPost]
public ActionResult BuildLaptop(FormCollection
formCollection)
{
Employee employee =
db.Employees.Find(Convert.ToInt32(formCollection["employeeID"]));
//Concrete Builder
ISystemBuilder systemBuilder
= new LaptopBuilder();
//Director
ConfigurationBuilder builder
= new ConfigurationBuilder();
builder.BuildSystem(systemBuilder, formCollection);
ComputerSystem system=
systemBuilder.GetSystem();
employee.SystemConfigurationDetails =
string.Format("RAM : {0}, HDDSize : {1}, TouchScreen: {2}"
, system.RAM, system.HDDSize, system.TouchScreen);
db.Entry(employee).State
= EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
Step 8 : Add build desktop action method as shown below
[HttpPost]
public ActionResult BuildDesktop(FormCollection
formCollection)
{
//Step 1
Employee employee
= db.Employees.Find(Convert.ToInt32(formCollection["employeeID"]));
//Step 2 Concrete Builder
ISystemBuilder systemBuilder
= new DesktopBuilder();
//Step 3 Director
ConfigurationBuilder builder
= new ConfigurationBuilder();
builder.BuildSystem(systemBuilder, formCollection);
//Step 4 return the system
ComputerSystem system =
systemBuilder.GetSystem();
employee.SystemConfigurationDetails =
string.Format("RAM : {0}, HDDSize : {1}, Keyboard: {2}, Mouse :
{3}"
, system.RAM, system.HDDSize, system.KeyBoard, system.Mouse);
db.Entry(employee).State
= EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");}
Step 9 : Create Desktop and Laptop views as shown below. On submit post the details to the respective action methods built in step 7 and step 8
@model Int32
@{
ViewBag.Title = "BuildSystem";
}
<h2>Build System</h2>
<style>
input[type=radio] {
border: 0px;
width: 100%;
height: 1em;
}
</style>
@using (Html.BeginForm("BuildDesktop", "Employees", FormMethod.Post ))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>System
Configuration</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.Hidden("employeeID", this.Model.ToString());
<div class="form-group">
@Html.Label("Memory", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("RAM",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "8GB", Value="8GB"},
new SelectListItem (){ Text = "16GB", Value="16GB"},
new SelectListItem (){ Text = "32GB", Value="32GB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.Label("Drive", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Drive",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "500GB", Value="500GB"},
new SelectListItem (){ Text = "1TB", Value="1TB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.Label("Mouse", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Mouse",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "WireLess", Value="USB-WireLess"},
new SelectListItem (){ Text = "Regular-USB", Value="USB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.Label("KeyBoard", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("KeyBoard",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "Wireless", Value="Wireless"},
new SelectListItem (){ Text = "Regular-USB", Value="Regular-USB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn
btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
@model Int32
@{
ViewBag.Title = "BuildSystem";
}
<h2>Build System</h2>
<style>
input[type=radio] {
border: 0px;
width: 100%;
height: 1em;
}
</style>
@using (Html.BeginForm("BuildLaptop", "Employees", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>System Configuration</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.Hidden("employeeID", this.Model.ToString());
<div class="form-group">
@Html.Label("Memory", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("RAM",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "8GB", Value="8GB"},
new SelectListItem (){ Text = "16GB", Value="16GB"},
new SelectListItem (){ Text = "32GB", Value="32GB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.Label("Drive", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
@Html.DropDownList("Drive",
new List<SelectListItem>() {
new SelectListItem (){ Text = "Select", Value="Select"},
new SelectListItem (){ Text = "500GB", Value="500GB"},
new SelectListItem (){ Text = "1TB", Value="1TB"},
},
htmlAttributes: new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.Label("Touch Enbled", htmlAttributes: new { @class = "control-label
col-md-2" })
<div class="col-md-10">
<div class="col-md-1">
<label>@Html.RadioButton("TouchScreen", "Yes", false, htmlAttributes: new { @class = "radio-inline" }) YES</label>
</div>
<div class="col-md-1">
<label>@Html.RadioButton("TouchScreen", "NO", false, htmlAttributes: new { @class = "radio-inline" }) NO</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn
btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Step 10 : Run the application and build the system. Notice that depending on the system type the respective system configurations are built.
Step 11 : With this we have successfully addressed requirement by using the builder design pattern
I hope now you got familiar with the builder design pattern.
In the next video, we will discuss how to implement fluent builder pattern and we will also discuss the differences between factory and the builder design pattern.
Looks like this problem needs to be resolved by Factory Method Pattern instead of using Builder Pattern to avoid duplicate code in the concrete builder classes.
ReplyDelete