Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Builder Design Pattern Implementation

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

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

builder design pattern implementation c#

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.

Design Patterns tutorial for beginners

1 comment:

  1. 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

It would be great if you can help share these free resources