C# Builder Pattern

Summary: in this tutorial, you will learn how to use the C# builder pattern to create a complex object step by step.

Introduction to the C# builder pattern

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

In practice, you use the Builder pattern for creating objects that require multiple steps, complex initialization, or multiple configurations.

The following UML diagram illustrates the Builder pattern:

C# Builder Pattern

The Builder pattern has four main participants:

  • Product: This is a class of complex objects with multiple parts.
  • Builder: This is an interface or abstract class that defines the steps for building the Product. The Builder interface has a set of methods for setting each property of the product.
  • ConcreteBuilder: This is a concrete class that implements the IBuilder interface. The ConcreteBuilder class has specific implementations for each of the methods.
  • Director: This is an optional class that controls the order in which the builder’s methods are called to build the Product. The Director class may also have additional logic for constructing the Product.

The following program demonstrates how to implement the Builder pattern in C#:

using static System.Console;

namespace BuilderPattern;

public class Product
{
    public string PartA {   get; set; }
    public string PartB {   get; set; }
}

public interface IBuilder
{
    IBuilder BuildPartA();
    IBuilder BuildPartB();
    Product GetProduct();
}

public class ConcreteBuilder : IBuilder
{
    public Product _product = new();

    public IBuilder BuildPartA()
    {
        _product.PartA = "Part A";
        return this;
    }

    public IBuilder BuildPartB()
    {
        _product.PartB = "Part B";
        return this;
    }

    public Product GetProduct()
    {
        return _product;
    }
}

public class Director
{
    private readonly IBuilder _builder;

    public Director(IBuilder builder)
    {
        _builder = builder;
    }

    public void Construct()
    {
        _builder.BuildPartA();
        _builder.BuildPartB();
    }
}

public class Client
{
    public static void Main()
    {
        var builder = new ConcreteBuilder();
        
        var director = new Director(builder);
        director.Construct();

        var product = builder.GetProduct();
        WriteLine($"Product Parts: {product.PartA}, {product.PartB}");
    }
}Code language: C# (cs)

Output:

Product Parts: Part A, Part BCode language: C# (cs)

How it works.

First, define a Product that has two parts A and B:

public class Product
{
    public string PartA {   get; set; }
    public string PartB {   get; set; }
}Code language: C# (cs)

Next, define an IBuilder interface that has methods for constructing the Product object from parts:

public interface IBuilder
{
    IBuilder BuildPartA();
    IBuilder BuildPartB();
    Product GetProduct();
}Code language: C# (cs)

Then, define a ConcreteBuilder class that implements the IBuilder interface:

public class ConcreteBuilder : IBuilder
{
    public Product _product = new();

    public IBuilder BuildPartA()
    {
        _product.PartA = "Part A";
        return this;
    }

    public IBuilder BuildPartB()
    {
        _product.PartB = "Part B";
        return this;
    }

    public Product GetProduct()
    {
        return _product;
    }
}Code language: C# (cs)

After that, define the Director class that constructs the Product using an instance of the IBuilder interface. The Construct() method uses the IBuilder instance to construct the Product.

public class Director
{
    private readonly IBuilder _builder;

    public Director(IBuilder builder)
    {
        _builder = builder;
    }

    public void Construct()
    {
        _builder.BuildPartA();
        _builder.BuildPartB();
    }
}Code language: C# (cs)

Finally, the Client class creates a ConcreteBuilder instance, injects it into the constructor of the Director object, and then uses the Director to construct the Product. It gets the Product from the GetProduct() method of the builder and shows it to the console:

public class Client
{
    public static void Main()
    {
        var builder = new ConcreteBuilder();
        
        var director = new Director(builder);
        director.Construct();

        var product = builder.GetProduct();
        WriteLine($"Product Parts: {product.PartA}, {product.PartB}");
    }
}Code language: C# (cs)

Summary

  • Use the Builder pattern to simplify the construction of complex objects and makes the code more flexible and maintainable.
Was this tutorial helpful ?