Builder Design Pattern

Builder Design Pattern

27 Jul 2024
Intermediate
173K Views
12 min read
Learn via Video Course & by Doing Hands-on Labs

⭐ .NET Design Patterns Course: Design Patterns in C# Online Training

Builder Design Pattern

Builder Design Pattern is an important design pattern in C# that allows you to develop complex objects step by step. It lets you build a complicated item by separating the creation process from the representation, allowing you to generate several representations of the same type of object. This pattern gives a straightforward way to build an object, especially when the process involves multiple steps or distinct configurations.

In this design pattern tutorial, we will look at the Builder Design Pattern, explaining what it is, when to use it, and how to implement it using examples. We will begin by studying "What is the Builder Design Pattern?"

What is a Builder Pattern?

  • The Builder pattern in C# is an object-oriented design pattern used to build complex objects step by step.
  • It differentiates between the construction process and the representation, allowing the same construction process to generate many representations.
  • A builder class typically has methods for configuring the various components of the product and a final Build function that creates the fully built item.

When to use the builder pattern?

The Builder pattern is applied when
  • Complex Object Construction: When an object requires sophisticated initialization or building that includes numerous processes or configurations.
  • Multiple Representations: When a single construction process must produce multiple representations or configurations of an entity.
  • Immutability: When you want to make immutable objects with different settings.
  • Code Readability and Maintainability: Encapsulate the building logic and separate it from the object representation to improve code readability and maintainability.

Builder Pattern - UML Diagram & Implementation

The UML class diagram for the implementation of the builder design pattern is given below:

The classes, interfaces, and objects in the above UML class diagram are as follows:

1. Builder

  • Role: Defines the abstract interface for manufacturing product pieces.
  • Responsibilities: Provide methods for building each component of the product and, in most cases, a way to retrieve the finished result.
  • Example

     public interface IHouseBuilder
    {
        void BuildWalls();
        void BuildRoof();
        void BuildDoors();
        void BuildWindows();
        House GetResult();
    }  

Explanation

The ConcreteHouseBuilder class implements the IHouseBuilder interface and creates a House object with specific properties, such as brick walls, a tile roof, wooden doors, and glass windows. It has methods for building each component of the house and a GetResult method that returns the final House object.

2. ConcreteBuilder

  • Role: Implements the Builder interface for creating and assembling Product components.
  • Responsibilities: Contains the precise implementation for each construction phase and the finished result.

Example

public class ConcreteHouseBuilder : IHouseBuilder
{
    private House _house = new House();

    public void BuildWalls() { _house.Walls = "Brick"; }
    public void BuildRoof() { _house.Roof = "Tile"; }
    public void BuildDoors() { _house.Doors = "Wooden"; }
    public void BuildWindows() { _house.Windows = "Glass"; }

    public House GetResult() { return _house; }
}

Explanation

The ConcreteHouseBuilder class, which implements the IHouseBuilder interface, creates a house object with brick walls, a tile roof, wooden doors, and glass windows. It also includes a method for returning the completed house.

3. Product

  • Role: The complex thing under construction.
  • Responsibilities: Represents the end product of the creation process, which is often a class with numerous attributes that may be configured using the builder.

Example

public class House
{
    public string Walls { get; set; }
    public string Roof { get; set; }
    public string Doors { get; set; }
    public string Windows { get; set; }

    public override string ToString()
    {
        return $"House with {Walls} walls, {Roof} roof, {Doors} doors, and {Windows} windows.";
    }
}

Explanation

The House class represents a house and has attributes for walls, roofs, doors, and windows that are described as strings. It overrides the ToString method and returns a descriptive string of the house's properties.

4. Director

Role: Use a Builder instance to manage the construction process.
Responsibilities: This section defines the order in which building stages are carried out to ensure that the product is created appropriately.

Example

public class HouseDirector
{
    private IHouseBuilder _builder;

    public HouseDirector(IHouseBuilder builder)
    {
        _builder = builder;
    }

    public void ConstructHouse()
    {
        _builder.BuildWalls();
        _builder.BuildRoof();
        _builder.BuildDoors();
        _builder.BuildWindows();
    }
}

Explanation

The HouseDirector class manages the construction of a House by utilizing an IHouseBuilder instance. It describes the sequence of building processes in its ConstructHouse technique to ensure that the house is created in the proper order. This distinction enables different builders to be employed interchangeably, resulting in diverse styles of homes.

How Does the Builder Pattern Work?

Consider the following example of how the Builder pattern works: We need to create a House object. A house can have various features, such as walls, roofs, doors, and windows. Building a house can be a difficult process; therefore, utilizing a Builder pattern might assist in managing the complexity.

Example

// Product
public class House
{
    public string Walls { get; set; }
    public string Roof { get; set; }
    public string Doors { get; set; }
    public string Windows { get; set; }

    public override string ToString()
    {
        return $"House with {Walls} walls, {Roof} roof, {Doors} doors, and {Windows} windows.";
    }
}

// Builder Interface
public interface IHouseBuilder
{
    void BuildWalls();
    void BuildRoof();
    void BuildDoors();
    void BuildWindows();
    House GetResult();
}

// ConcreteBuilder
public class ConcreteHouseBuilder : IHouseBuilder
{
    private House _house = new House();

    public void BuildWalls() { _house.Walls = "Brick"; }
    public void BuildRoof() { _house.Roof = "Tile"; }
    public void BuildDoors() { _house.Doors = "Wooden"; }
    public void BuildWindows() { _house.Windows = "Glass"; }

    public House GetResult() { return _house; }
}

// Director
public class HouseDirector
{
    private IHouseBuilder _builder;

    public HouseDirector(IHouseBuilder builder)
    {
        _builder = builder;
    }

    public void ConstructHouse()
    {
        _builder.BuildWalls();
        _builder.BuildRoof();
        _builder.BuildDoors();
        _builder.BuildWindows();
    }
}

// Usage
public class Program
{
    public static void Main()
    {
        IHouseBuilder builder = new ConcreteHouseBuilder();
        HouseDirector director = new HouseDirector(builder);

        director.ConstructHouse();
        House house = builder.GetResult();

        System.Console.WriteLine(house);
    }
}

Explanation

This example uses the Builder pattern, with House as the product class, IHouseBuilder as the builder interface, ConcreteHouseBuilder as the concrete builder that implements the construction phases, and HouseDirector directing the building process. The Program class builds a house and prints its description.

Output

House with Brick walls, Tile roof, Wooden doors, and Glass windows.

Advantages of the Builder Pattern:

  • Separation of Concerns: Separates the building logic of complex objects from their representation.
  • Flexible construction: Allows for multiple representations of a product using the same method.
  • Readability and Maintenance: Improves code readability and maintainability by encapsulating the construction process.
Summary
The C# Builder Design Pattern separates the creation process from the representation, allowing for the step-by-step construction of complicated objects. This pattern configures components using a builder class and manages the creation sequence with a director, allowing for different representations of the same object. Encapsulating the building logic increases code readability, maintainability, and adaptability. Also, consider our .NET design patterns training for a better understanding of other design patterns concepts.
Share Article

Live Classes Schedule

Our learn-by-building-project method enables you to build practical/coding experience that sticks. 95% of our learners say they have confidence and remember more when they learn by building real world projects.
ASP.NET Core Certification TrainingSep 15SAT, SUN
Filling Fast
09:30AM to 11:30AM (IST)
Get Details
Software Architecture and Design TrainingSep 22SAT, SUN
Filling Fast
07:00AM to 09:00AM (IST)
Get Details
ASP.NET Core Certification TrainingSep 29SAT, SUN
Filling Fast
08:30PM to 10:30PM (IST)
Get Details
ASP.NET Core ProjectOct 13SAT, SUN
Filling Fast
10:00AM to 12:00PM (IST)
Get Details

Can't find convenient schedule? Let us know

About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

Shailendra Chauhan is the Founder and CEO at ScholarHat by DotNetTricks which is a brand when it comes to e-Learning. He provides training and consultation over an array of technologies like Cloud, .NET, Angular, React, Node, Microservices, Containers and Mobile Apps development. He has been awarded Microsoft MVP 8th time in a row (2016-2023). He has changed many lives with his writings and unique training programs. He has a number of most sought-after books to his name which has helped job aspirants in cracking tough interviews with ease.
Accept cookies & close this