Wednesday, February 15, 2012

Design Patterns : Builder pattern Implementation

Builder pattern falls under the Creational design pattern. The Builder pattern separates the construction phase of a complex object from its representation so that the same construction logic can be used for different objects and the output representation may be different. Using the same construction logic, we will get different object representations.

I have used the scenario for creation of reports as the example. We can create either PDF or Excel reports.

ReportBuilder class has the construction logic for building the individual parts of the Report. Director takes ReportBuilder as argument and then defines the sequence for building the report. The end result is the Report which can either be Excel or PDF.

The code snippet for this pattern is as seen below :

using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace DesignPatterns
{
    // Client invoking class
    public class Client
    {
        public static void Main()
        {
            // Create a PDF report
            ReportBuilder pdfBuilder = new PDFBuilder();
            Director dir = new Director();
            Report pdfReport = dir.GenerateReport(pdfBuilder);
            // Print content
            Console.WriteLine(pdfReport.Header);
            Console.WriteLine(pdfReport.Content);
            Console.WriteLine(pdfReport.Footer);
            // Create a Excel report
            ReportBuilder excelBuilder = new ExcelBuilder();
            Report excelReport = dir.GenerateReport(excelBuilder);
            // Print content
            Console.WriteLine(excelReport.Header);
            Console.WriteLine(excelReport.Content);
            Console.WriteLine(excelReport.Footer);
            Console.ReadLine();
        }
    }

    // Report or Product
    public class Report
    {
        public string ReportType;
        public string Header;
        public string Footer;
        public string Content;
    }

    // Report Builder - Builder is responsible for defining
    // the construction process for individual parts. Builder
    // has those individual processes to initialize and
    // configure the report.
    public abstract class ReportBuilder
    {
        public Report report;
        public void CreateReport()
        {
            report = new Report();
        }
        public abstract void SetReportType();
        public abstract void SetHeader();
        public abstract void SetFooter();
        public abstract void SetContent();
        public Report DispatchReport()
        {
            return report;
        }
    }

    // PDF Report class
    public class PDFBuilder : ReportBuilder
    {
        public override void SetReportType()
        {
            report.ReportType = "PDF";
        }
        public override void SetHeader()
        {
            report.Header = "PDF Header";
        }
        public override void SetFooter()
        {
            report.Footer = "PDF Footer";
        }
        public override void SetContent()
        {
            report.Content = "PDF Content";
        }
    }

    // Excel Report class
    public class ExcelBuilder : ReportBuilder
    {
        public override void SetReportType()
        {
            report.ReportType = "Excel";
        }
        public override void SetHeader()
        {
            report.Header = "Excel Header";
        }
        public override void SetFooter()
        {
            report.Footer = "Excel Footer";
        }
        public override void SetContent()
        {
            report.Content = "Excel Content";
        }
    }

    ///
    /// Director takes those individual processes from the builder
    /// and defines the sequence to build the report.
    ///
    public class Director
    {
        public Report GenerateReport(ReportBuilder reportBuilder)
        {
            reportBuilder.CreateReport();
            reportBuilder.SetReportType();
            reportBuilder.SetHeader();
            reportBuilder.SetContent();
            reportBuilder.SetFooter();
            return reportBuilder.DispatchReport();
        }
    }
}

Another Example:

Builder falls under the type of creational pattern category. Builder pattern helps us to separate the construction of a complex object from its representation so that the same construction process can create different representations. Builder pattern is useful when the construction of the object is very complex. The main objective is to separate the construction of objects and their representations. If we are able to separate the construction and representation, we can then get many representations from the same construction.


Figure: - Builder concept


To understand what we mean by construction and representation lets take the example of the below ‘Tea preparation’ sequence.

You can see from the figure ‘Tea preparation’ from the same preparation steps we can get three representation of tea’s (i.e. Tea with out sugar, tea with sugar / milk and tea with out milk).


Figure: - Tea preparation


Now let’s take a real time example in software world to see how builder can separate the complex creation and its representation. Consider we have application where we need the same report to be displayed in either ‘PDF’ or ‘EXCEL’ format. Figure ‘Request a report’ shows the series of steps to achieve the same. Depending on report type a new report is created, report type is set, headers and footers of the report are set and finally we get the report for display.


Figure: - Request a report

Now let’s take a different view of the problem as shown in figure ‘Different View’. The same flow defined in ‘Request a report’ is now analyzed in representations and common construction. The construction process is same for both the types of reports but they result in different representations.


Figure: - Different View


We will take the same report problem and try to solve the same using builder patterns. There are three main parts when you want to implement builder patterns.

Builder: - Builder is responsible for defining the construction process for individual parts. Builder has those individual processes to initialize and configure the product.
Director: - Director takes those individual processes from the builder and defines the sequence to build the product.
Product: - Product is the final object which is produced from the builder and director coordination.

First let’s have a look at the builder class hierarchy. We have a abstract class called as ‘ReportBuilder’ from which custom builders like ‘ReportPDF’ builder and ‘ReportEXCEL’ builder will be built.


Figure: - Builder class hierarchy

Figure ‘Builder classes in actual code’ shows the methods of the classes. To generate report we need to first Create a new report, set the report type (to EXCEL or PDF) , set report headers , set the report footers and finally get the report. We have defined two custom builders one for ‘PDF’ (ReportPDF) and other for ‘EXCEL’ (ReportExcel). These two custom builders define there own process according to the report type.


Figure: - Builder classes in actual code

Now let’s understand how director will work. Class ‘clsDirector’ takes the builder and calls the individual method process in a sequential manner. So director is like a driver who takes all the individual processes and calls them in sequential manner to generate the final product, which is the report in this case. Figure ‘Director in action’ shows how the method ‘MakeReport’ calls the individual process to generate the report product by PDF or EXCEL.



Figure: - Director in action

The third component in the builder is the product which is nothing but the report class in this case.


Figure: - The report class

Now let’s take a top view of the builder project. Figure ‘Client,builder,director and product’ shows how they work to achieve the builder pattern. Client creates the object of the director class and passes the appropriate builder to initialize the product. Depending on the builder the product is initialized/created and finally sent to the client.


Figure: - Client, builder, director and product

The output is something like this. We can see two report types displayed with their headers according to the builder.


Figure: - Final output of builder

Reference:

No comments:

Post a Comment