Builder Design Pattern in C#

Builder Design Pattern in C# with Examples

In this article, I am going to discuss the Builder Design Pattern in C# with Examples. Please read our previous article where we discussed the Abstract Factory Design Pattern in C# with Examples. The Builder Design Pattern falls under the category of the Creational Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is the Builder Design Pattern?
  2. Understanding the Builder Design Pattern with a real-time example.
  3. Understanding the class diagram of the Builder Design Pattern?
  4. Implementing the Builder Design Pattern in C#.
  5. When to use the Builder Design Pattern in real-time applications.
What is the Builder Design Pattern?

According to GoF, the Builder Design Pattern builds a complex object using many simple objects and using a step-by-step approach. The Process of constructing a complex object should be generic so that the same construction process can be used to create different representations of the same complex object.

So, the Builder Design Pattern is all about separating the construction process from its representation. When the construction process of your object is very complex then only you need to use to Builder Design Pattern. If this is not clear at the moment then don’t worry we will try to understand this with an example.

Please have a look at the following diagram. Here, the Laptop is a complex object. In order to build a laptop, we have to use many small objects like LCD Displays, USB Ports, Wireless, Hard Drives, Pointing Devices, Battery, Memory, DVD/CD Reader, Keyboard, Plastic Case, etc. So, we have to assemble all these small objects to build the laptop complex objects.

What is the Builder Design Pattern?

So, to build the complex object laptop we need to define some kind of generic process something like below.
1. Plug the memory
2. Plug the Hard Drive
3. Plug the battery
4. Plug the Keyboard
……
……
10. Cover the Laptop with a plastic case

So, using the above process we can create different types of laptops such as a laptop with a 14-inch screen or a 17-inch screen. Laptop with 4GB RAM or 8GB RAM. So, like this, we can create different kinds of laptops. So, all the laptop creations will follow the same generic process. So, now if you read the definition, then definitely you will understand the definition of Builder Design Pattern.

Example to Understand Builder Design Pattern:

Let us understand the Builder Design Pattern in C# with one Real-Time Example. Suppose we want to develop an application for displaying the reports. The reports we need to display either in Excel or in PDF format. That means, we have two types of representation of the reports. In order to understand this better, please have a look at the following diagram.

Example to Understand Builder Design Pattern

As you can see, in the above image, we are generating the report either in Excel or PDF formats. Here, the construction process involves several steps such as Creating a new report and setting the report type, report header, content, and footer. If you look at the final output we have one PDF representation and one Excel representation. Please have a look at the following diagram to understand the construction process and its representation. As you can see, the construction process is the same, but with the same construction process, we are getting two types of reports.

Example to Understand Builder Design Pattern in C#

Understanding the UML (or Class) Diagram of Builder Design Pattern in C#

Let us understand the UML or Class Diagram and understand the different components involved in the Builder Design Pattern. In order to understand this please have a look at the following diagram.

Understanding the UML (or Class) Diagram of Builder Design Pattern

In order to separate the construction process from its representation, the builder design pattern Involve four components. They are as follows. 

  1. Abstract Builder: The Builder is an interface that defines all the steps which are used to make the concrete product. 
  2. Concrete Builder: The Concrete Builder Classes implements the Abstract Builder interface and provides implementation to all the abstract methods. The Concrete Builder is responsible for constructing and assembling the individual parts of the product by implementing the Builder interface. It also defines and tracks the representation it creates.
  3. Director: The Director takes those individual processes from the Builder and defines the sequence to build the product.
  4. Product: The Product is a class and we want to create this product object using the builder design pattern. This class defines different parts that will make the product.

Note: If you are not understanding the above component at the moment, then don’t worry, once we see the example, then we will compare the example with the above UML diagram and compare our example with the above component. And I am sure after then you will understand the above UML Diagram and understand the different components of the Builder Design Pattern.

Implementation of Builder Design Pattern in C#:

Let us implement the Excel and PDF Report example that we discussed using the Builder Design Pattern in C# step by step. 

Step 1: Creating the Product

Create a class file with the name Report.cs and then copy and paste the following code into it. This is our product class and within this class, we define the attributes (such as ReportHeader, ReportType, ReportFooter, and ReportContent) which are common to create a report. We also define one method i.e. DisplayReport to display the report details in the console.

using System;
namespace BuilderDesignPattern
{
    // It makes sense to use the Builder Design Pattern only 
    // when your products are quite complex 
    // and require extensive configuration.
    // Using the following Report Product class, we can configure different types of Product
    public class Report
    {
        public string ReportType { get; set; }
        public string ReportHeader { get; set; }
        public string ReportFooter { get; set; }
        public string ReportContent { get; set; }

        public void DisplayReport()
        {
            Console.WriteLine("Report Type :" + ReportType);
            Console.WriteLine("Header :" + ReportHeader);
            Console.WriteLine("Content :" + ReportContent);
            Console.WriteLine("Footer :" + ReportFooter);
        }
    }
}

Once we know the definition of the Product we are building, now we need to create the Builder.

Step 2: Creating the Abstract Builder Class.

Create a class file with the name ReportBuilder.cs and then copy and paste the following into it. This is going to be an abstract class and this class provides the blueprint to create different types of products. As it is abstract, it can have the capabilities to have both abstract and non-abstract methods. The subclasses are going to implement this ReportBuilder abstract class and need to provide implementations for all the abstract methods it contains. The Builder Abstract Class specifies methods for creating the different parts of the Product objects.

namespace BuilderDesignPattern
{
    // The Builder Abstract Class specifies methods for creating the different parts
    // of the Product objects.
    public abstract class ReportBuilder
    {
        protected Report reportObject;

        public abstract void SetReportType();
        public abstract void SetReportHeader();
        public abstract void SetReportContent();
        public abstract void SetReportFooter();

        public void CreateNewReport()
        {
            reportObject = new Report();
        }

        public Report GetReport()
        {
            return reportObject;
        }
    }
}

Notice, here we have four abstract methods. So, each subclass of ReportBuilder will need to implement those four abstract methods in order to properly build a report. Now, we need to create a few concrete builder classes by implementing the above ReportBuilder interface.

Step 3: Creating Concrete Builder Classes.

The Concrete Builder classes follow the Builder interface and provide specific implementations of the building steps. The Application may have several variations of Builders, implemented differently. In our example, we are dealing with two types of reports i.e. Excel and PDF. So, we need to create two concrete builder classes by implementing the ReportBuilder Abstract Class and providing implementation to the ReportBuilder Abstract Methods.

ExcelReport.cs

Create a class file with the name ExcelReport.cs and then copy and paste the following code into it. This ExcelReport class implements the ReportBuilder abstract class and implements the four abstract methods which is the blueprint for creating the report objects. This class is basically used to provide the blueprint for creating the Excel Report. 

namespace BuilderDesignPattern
{
    // The Following Concrete Builder Implementd the ReportBuilder Abstract Class and 
    // provide specific implementations of the steps for Creating ExcelReport. 
    public class ExcelReport : ReportBuilder
    {
        public override void SetReportContent()
        {
            reportObject.ReportContent = "Excel Content Section";
        }

        public override void SetReportFooter()
        {
            reportObject.ReportFooter = "Excel Footer";
        }

        public override void SetReportHeader()
        {
            reportObject.ReportHeader = "Excel Header";
        }

        public override void SetReportType()
        {
            reportObject.ReportType = "Excel";
        }
    }
}
PDFReport.cs

Create a class file with the name PDFReport.cs and then copy and paste the following code into it. This class also implements the ReportBuilder abstract class and implements the four abstract methods which is the blueprint for creating the report objects. The following PDFReport class is used to create the Report in PDF format.

namespace BuilderDesignPattern
{
    // The Following Concrete Builder Implementd the ReportBuilder Abstract Class and 
    // provide specific implementations of the steps for Creating PDFReport. 
    public class PDFReport : ReportBuilder
    {
        public override void SetReportContent()
        {
            reportObject.ReportContent = "PDF Content Section";
        }

        public override void SetReportFooter()
        {
            reportObject.ReportFooter = "PDF Footer";
        }

        public override void SetReportHeader()
        {
            reportObject.ReportHeader = "PDF Header";
        }

        public override void SetReportType()
        {
            reportObject.ReportType = "PDF";
        }
    }
}

Once we have the required Concrete Builder Classes, now we need to create the Director. The Director will execute the required steps in a particular order to create a particular product.

Step 4: Creating the Director

The Director Class in Builder Design Pattern is only responsible for executing the building steps in a particular order. These steps are so generic that these steps will produce different products. It is helpful when producing products according to a specific order or configuration.

Please create a class file with the name ReportDirector.cs and then copy and paste the following code into it. The following class is having one generic method i.e. MakeReport which will take the ReportBuilder instance as an input parameter and then create and return a particular report object. See, this class will call the respective methods of the ReportBuilder object (i.e. an object of either ExcelReport or PDFReport ) in a particular order to create a particular format report.

namespace BuilderDesignPattern
{
    // The Director is only responsible for executing the building steps in a particular order. 
    // It is helpful when producing products according to a specific order or configuration. 
    public class ReportDirector
    {
        public Report MakeReport(ReportBuilder reportBuilder)
        {
            reportBuilder.CreateNewReport();
            reportBuilder.SetReportType();
            reportBuilder.SetReportHeader();
            reportBuilder.SetReportContent();
            reportBuilder.SetReportFooter();

            return reportBuilder.GetReport();
        }
    }
}

Note: This MakeReport Method is so generic that it can create and return different types of report objects. Once we have the Director and Concrete Builder, now they can be used by the Client to create different types of Reports. In our example, the Client is nothing but the Main method of the Program class.

Step 5: Client Code

The client code in Builder Design Pattern is going to create a builder object, then pass that builder object to the director and then the director will initiate the construction process. The end result is nothing the product is retrieved from the builder object.

In our example, the Main method of the Program class is going to be the Client. So, please modify the Main Method of the Program class as shown below. Here, first, we will create an instance of the ReportDirector class and then create an instance of PDFReport class. Once we have the ReportDirector instance and PDFReport instance, then we call the MakeReport method on the ReportDirector instance bypassing the PDFReport instance as an argument that will create and return the report in PDF format. The same process is also for Excel reports. The following code is self-explained, so please go through the comment lines for a better understanding.

using System;
namespace BuilderDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Constructing the PDF Report
            // Step1: Create a Builder Object 
            // Creating PDFReport Builder Object
            PDFReport pdfReport = new PDFReport();

            // Step2: Pass the Builder Object to the Director
            // First Create an instance of ReportDirector
            ReportDirector reportDirector = new ReportDirector();
            // Then Pass the pdfReport Builder Object to the MakeReport Method of ReportDirector
            // The ReportDirector will return one of the Representations of the Product
            Report report = reportDirector.MakeReport(pdfReport);

            // Step3: Display the Report by calling the DisplayReport method of the Product
            report.DisplayReport();

            Console.WriteLine("-------------------");
            // Constructing the Excel Report
            // The Process is going to be the same
            ExcelReport excelReport = new ExcelReport();
            report = reportDirector.MakeReport(excelReport);
            report.DisplayReport();

            Console.ReadKey();
        }
    }
}

Now run the application and you should get the output as shown in the below image.

When to use the Builder Design Pattern in Real-Time Applications?

Builder Design Pattern Components in Our Example

Now, let us see the Builder Design Pattern UML Diagram Component with our Example so that you can easily understand the UML Diagram.

Builder Design Pattern UML Diagram

Builder Design Pattern Components in Our Example

  1. Client: Main Method of Program Class
  2. Builder: ReportBuilder.cs
  3. Concrete Builder: ExcelReport.cs and PDFReport.cs
  4. Director: ReportDirector.cs
  5. Product: Report.cs
Advantages of Builder Design Pattern:
  1. With Builder Design Pattern, the Application Code is more Maintainable and Readable.
  2. Less prone to errors as we have a method that returns the finally constructed object.
Disadvantages of Builder Design Pattern:
  1. The number of lines of code increases in the builder design patterns, but it makes sense as the effort pays off in terms of maintainability and readability.
When to use the Builder Design Pattern in Real-Time Applications?

We need to use the Builder Design Pattern in C# in the following scenarios.

  1. When we want to make a complex object by specifying only its type and content. The object is constructed from the details of its construction process.
  2. When we decouple the process of building a complex object from the parts that make up the object.
  3. When we want to isolate the code for construction and representation.

In the next article, I am going to discuss the Builder Design Pattern in Real-time Example in C#. Here, in this article, I try to explain the Builder Design Pattern in C# with Examples. I hope you understood the need and use of the Builder Design Pattern in C#.

2 thoughts on “Builder Design Pattern in C#”

  1. blank

    Very good. Just missed public in below class as below

    class ExcelReport : ReportBuilder
    should be
    public class ExcelReport : ReportBuilder

Leave a Reply

Your email address will not be published. Required fields are marked *