Builder Design Pattern


Here, we will explain builder Design Pattern with example in C#.

Builder Design Pattern Introduction

The Builder Design Pattern is a creational design pattern that helps in constructing complex objects step by step. It separates the construction of an object from its representation, allowing the same construction process to create different representations.

OR

The Builder Design Pattern is a way to build complex objects in a simple and organized manner. Instead of creating the object all at once (which can be confusing when there are many details), the Builder pattern lets you build the object step by step. Each step handles a specific part of the object, making it easier to customize or change the way the object is created.

Example - Imagine building a house. Some houses may have a garage, a garden, and a pool, while others may only have basic features. The Builder pattern lets you choose which features to include, while still following the same steps to build the house.

Advantages of the Builder Pattern

  1. Construct Complex Objects - It simplifies the creation of complex objects that require multiple steps and configurations.
  2. Code Clarity - Provides better readability and maintainability by isolating the construction code.
  3. Flexible and Reusable - The same builder can be reused for different object representations, reducing code duplication.
  4. Immutability - Allows the construction of immutable objects while making it easy to manage object states through intermediate builders.
  5. Step-by-step Construction - It allows for the creation of an object in a controlled manner, where each step of construction can be specified independently.
  6. Less Error-Prone - The process ensures that the object is constructed only when it is complete, reducing the likelihood of incomplete or invalid objects.
  7. Easier Maintenance - Changes in object construction can be easily accommodated without affecting client code.

When to Use the Builder Pattern

  • When constructing complex objects - Use it when creating objects that require many configurations or steps.
  • When you want to avoid a large constructor - If an object has many optional parameters, the builder pattern is a good alternative to telescoping constructors.
  • When you need different representations of the same object - It’s useful when the object can be represented in different ways.
  • When you want to improve the readability of object creation - Instead of having one massive constructor, the builder pattern breaks down the creation into individual methods.
  • When the creation process involves multiple steps - If an object needs to be created step by step or needs to enforce a certain order of operations.

Problems in a System Without Builder Pattern

  • Complex Constructors - Without a builder, objects requiring many parameters can result in long, unreadable constructors (telescoping constructors).
  • Hard to Maintain - Changes in object construction may require modifying multiple parts of the code, leading to higher maintenance costs.
  • Difficult Object Creation - When object construction requires many steps, client code can become bloated with redundant or repetitive object setup logic.
  • Code Duplication - Similar object creation logic will be duplicated across different parts of the system.
  • Poor Scalability - Adding new ways to construct an object without a builder pattern requires modification of the constructor, leading to more rigid and less scalable code.

Components of Builder Pattern

  1. Product - The complex object being built. In this case, the home.
  2. Builder - Specifies an abstract interface for creating parts of the product object.
  3. Concrete Builder - Implements the builder interface and constructs the actual object.
  4. Director - Controls the construction process. It uses the builder to construct the object.
  5. Client - The end user of the Builder who sets up the desired object.

Example - Building a Home

Let’s take the example of constructing a home. A home might have optional features like a garage, a garden, and a swimming pool, but not all homes have the same set of features. Using the Builder pattern, we can construct homes with different features without having an overly complex constructor.

  • Step 1: Lay the foundation.
  • Step 2: Build the walls.
  • Step 3: Add the roof.
  • Step 4: Optionally add a garage, garden, or pool.

This way, you can create a luxury house (with all the extras) or a simple house (with just the basics) using the same steps, just by choosing which features to include.

Builder Design Pattern

Luxury House

Builder Design Pattern

Simple House

  1. Luxury Home - This home is built with a luxury foundation, structure, and roof, and it includes a garage, garden, and swimming pool.
  2. Simple Home - This home is built with a basic foundation, structure, and roof, and it does not include luxury features like a garage, garden, or swimming pool.

Code Example

Here’s an example demonstrating how to use the Builder pattern to construct different types of homes.

using System;

public class Home
{
    public string Foundation { get; set; }
    public string Structure { get; set; }
    public string Roof { get; set; }
    public bool HasGarage { get; set; }
    public bool HasGarden { get; set; }
    public bool HasSwimmingPool { get; set; }

    public override string ToString()
    {
        return $"Home with {Foundation}, {Structure}, {Roof}, " +
               $"Garage: {HasGarage}, Garden: {HasGarden}, Swimming Pool: {HasSwimmingPool}";
    }
}

public interface IHomeBuilder
{
    void BuildFoundation();
    void BuildStructure();
    void BuildRoof();
    void AddGarage();
    void AddGarden();
    void AddSwimmingPool();
    Home GetHome();
}

public class LuxuryHomeBuilder : IHomeBuilder
{
    private Home _home = new Home();

    public void BuildFoundation() => _home.Foundation = "Concrete, steel, and glass foundation";
    public void BuildStructure() => _home.Structure = "Luxury Structure with 5 bedrooms";
    public void BuildRoof() => _home.Roof = "Luxury Roof with solar panels";
    public void AddGarage() => _home.HasGarage = true;
    public void AddGarden() => _home.HasGarden = true;
    public void AddSwimmingPool() => _home.HasSwimmingPool = true;

    public Home GetHome() => _home;
}

public class SimpleHomeBuilder : IHomeBuilder
{
    private Home _home = new Home();

    public void BuildFoundation() => _home.Foundation = "Basic concrete foundation";
    public void BuildStructure() => _home.Structure = "Simple Structure with 2 bedrooms";
    public void BuildRoof() => _home.Roof = "Simple roof with tiles";
    public void AddGarage() => _home.HasGarage = false;
    public void AddGarden() => _home.HasGarden = false;
    public void AddSwimmingPool() => _home.HasSwimmingPool = false;

    public Home GetHome() => _home;
}

public class HomeDirector
{
    private IHomeBuilder _homeBuilder;

    public HomeDirector(IHomeBuilder homeBuilder)
    {
        _homeBuilder = homeBuilder;
    }

    public void ConstructHome()
    {
        _homeBuilder.BuildFoundation();
        _homeBuilder.BuildStructure();
        _homeBuilder.BuildRoof();
    }

    public void AddLuxuryFeatures()
    {
        _homeBuilder.AddGarage();
        _homeBuilder.AddGarden();
        _homeBuilder.AddSwimmingPool();
    }

    public Home GetHome()
    {
       return _homeBuilder.GetHome();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Build a luxury home
        IHomeBuilder luxuryBuilder = new LuxuryHomeBuilder();
        HomeDirector director = new HomeDirector(luxuryBuilder);
        director.ConstructHome();
        director.AddLuxuryFeatures();
        Home luxuryHome = director.GetHome();
        Console.WriteLine(luxuryHome.ToString());

        // Build a simple home
        IHomeBuilder simpleBuilder = new SimpleHomeBuilder();
        director = new HomeDirector(simpleBuilder);
        director.ConstructHome();
        Home simpleHome = director.GetHome();
        Console.WriteLine(simpleHome.ToString());
    }
}

How It Works

  • The Home class represents the final object you are building (with different features like a garage, garden, etc.).
  • The IHomeBuilder interface defines the methods to build parts of the home.
  • The LuxuryHomeBuilder and SimpleHomeBuilder are concrete implementations of the builder, responsible for building different types of homes.
  • The HomeDirector class controls the process of building the home, ensuring the correct steps are followed.
  • In the Program.Main() method, you can see how both a luxury and simple home are built step by step.

Output

Builder Design Pattern

Real-World Example - Builder Pattern in Life

A real-world example could be the process of building a pizza. A pizza has various components: dough, sauce, toppings, cheese, etc. With a builder pattern, you can create different variations of pizza (e.g., vegetarian, meat-lover, thin-crust) by assembling the components in a step-by-step manner.

For instance:

  • Start with a dough.
  • Add a layer of sauce.
  • Add your choice of toppings (e.g., vegetables, meats, etc.).
  • Add cheese.

This mirrors the builder pattern, where different kinds of pizzas can be created by specifying their ingredients step by step.

Application of Builder Design Pattern

  • UI Frameworks - When creating complex UI components that can be customized in various ways.
  • Serialization/Deserialization - In some systems, builder patterns can be used to create objects from a series of steps during the deserialization process.
  • Database Query Builders - For constructing complex database queries where conditions and filters can be added in stages.
  • Immutable Objects - For creating immutable objects with many configuration options without using massive constructors.
  • Game Development - To create various types of game characters, levels, or objects in stages.
  • API Clients - Used to build HTTP requests with multiple parameters (headers, query strings, body, etc.) before sending them.

Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question