Welcome to deBUG.to Community where you can ask questions and receive answers from Microsoft MVPs and other experts in our community.
0 like 0 dislike
869 views
in Blog Post by 63 69 85

In this article, we will discuss Builder Design Pattern by understanding what is Builder Design Pattern, the UML diagram. Moreover, why use Builder Pattern and the Implementation code using C#.

It’s recommended to read what is What is Design Patterns

What is Builder Design Pattern?

Builder is a creational design pattern that separates the construction of a complex object from its representation so that the same construction process can create different representations.

When the construction process of your object is very complex then only you need to use to Builder Design Pattern.

UML Diagram

Let’s see the UML diagram of it. And the description of each class.

Name

Description

Ibuilder

This is an interface that is used to define all the steps required to create a product.

ConcreteBuilder

This is a class that implements the Builder interface to create a complex product.

Product

This is a class that defines the parts of the complex object which are to be generated by the Builder Pattern.

Director

This is a class that is used to construct an object using the Builder interface.

Why use Builder Design Pattern?

We need to use a builder pattern in these two scenario:

  1. When it’s necessary to use a constructor with a long parameter list, or when there’s a long list of constructors with different parameters.
  2. When it’s necessary to build different representations of the same object. That is when objects of the same class with different characteristics are needed.

It makes sense to use the Builder pattern only when your products are quite complex and require extensive configuration.

Implementation of the Builder Design Patterns in C#

The below steps are the way to implement a Builder Design Pattern.

  1. Make sure that you can clearly define the common construction steps for building all available product representations. Otherwise, you won’t be able to proceed with implementing the pattern.
  2. Declare these steps in the base builder interface.
  3. Create a concrete builder class for each of the product representations and implement their construction steps.
  4. Think about creating a director class. It may encapsulate various ways to construct a product using the same builder object.
  5. The client code creates both the builder and the director objects. Before construction starts, the client must pass a builder object to the director.
using System;
using System.Collections.Generic;

namespace BuilderDesignPattern
{
    public interface IBuilder
    {
        void BuildPartA();

        void BuildPartB();

        void BuildPartC();
        void Reset();
    }
    // The Concrete Builder classes follow the Builder interface and provide
    // specific implementations of the building steps.
    public class ConcreteBuilder : IBuilder
    {
        private Product _product = new Product();

        public ConcreteBuilder()
        {
            Reset();
        }

        public void Reset()
        {
            _product = new Product();
        }

        // All production steps work with the same product instance.
        public void BuildPartA()
        {
            _product.Add("PartA1");
        }

        public void BuildPartB()
        {
            _product.Add("PartB1");
        }

        public void BuildPartC()
        {
            _product.Add("PartC1");
        }

        public Product GetProduct()
        {
            Product result = _product;

            Reset();

            return result;
        }
    }

    public class Product
    {
        private List<object> _parts = new List<object>();

        public void Add(string part)
        {
            _parts.Add(part);
        }

        public void ListParts()
        {
            Console.WriteLine("\nProduct Parts -------");
            foreach (string part in _parts)
                Console.WriteLine(part);
        }
    }

    // The Director is only responsible for executing the building steps in a
    // particular sequence. It is helpful when producing products according to a
    // specific order or configuration.
    public class Director
    {
        public void BuildMinimalProduct(IBuilder builder)
        {
            builder.BuildPartA();
        }

        public void BuildFullFeaturedProduct(IBuilder builder)
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.BuildPartC();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // The client code creates a builder object, passes it to the
            // director and then initiates the construction process.
            var director = new Director();
            var builder = new ConcreteBuilder();

            Console.WriteLine("Standard basic product:");
            director.BuildMinimalProduct(builder);
            builder.GetProduct().ListParts();

            Console.WriteLine("\nStandard full featured product:");
            director.BuildFullFeaturedProduct(builder);
            builder.GetProduct().ListParts();

            // Note: the Builder pattern can be used without a Director
            // class.
            Console.WriteLine("\nCustom product:");
            builder.BuildPartA();
            builder.BuildPartC();
            builder.GetProduct().ListParts();
        }
    }
}

Expected output

Standard basic product:

Product Parts -------
PartA1

Standard full featured product:

Product Parts -------
PartA1
PartB1
PartC1

Custom product:

Product Parts -------
PartA1
PartC1

Reference

  1. Builder - refactoring.guru
  2. C# Builder Design Pattern - Dofactory

If you don’t ask, the answer is always NO!
...