Builder Pattern in C#
Tags: beginners, programming, tutorial, csharp
Published: 2022-08-30 12:38:47

_Originally posted [here](https://dfordebugging.wordpress.com/2022/08/30/builder-pattern-in-c/)_

The **Builder** is a creational design pattern that allows us to
construct complex objects step by step. The pattern separates an object from its representation so that the same construction process can create different representations.

The **Builder** is a handy tool when we have a collection of pieces for a complex object and need to build them all together. With this pattern, we can initialize each piece of the complex object step by step and then build them all up to a complete object.

You can find the example code of this post, on [Github](https://github.com/Kalkwst/DesignPatterns)

## Conceptualizing the Problem

Imagine a complex object that requires step-by-step initialization of many fields, some of them optional. Such initialization code is usually either buried under a monstrous constructor with lots of parameters or scattered around numerous constructors that only initialize some fields.

Let's think about how to create a `Pizza` object. To build a simple pizza, we need to add a simple dough, some tomato sauce and shredded cheese. But what if we want to build a bigger, better pizza, with cream cheese in the crust, and other goodies (like pepperoni, bell peppers, and mozzarella cheese)?

The simplest solution is to extend the base `Pizza` class and create a set of subclasses to cover all combinations of the parameters. But eventually, you'll end up with a considerable number of subclasses. Any new parameter will require growing this hierarchy even more.

There's another approach that doesn't evolve creating more subclasses. We can create a giant constructor right in the base `Pizza` class with all possible parameters that control the pizza object. While this approach indeed eliminates the need for multiple subclasses, it creates another problem.

In most cases, the majority of parameters will be unused, making the constructor calls pretty ugly. For instance, only a fraction of pizzas have pineapple as a topping, so the parameters related to it will be useless most of the time.

The **Builder** pattern suggests that we extract the object construction code out of this own class and move it to a separate object called the *builder.*

The pattern organizes object construction into a distinct set of steps (`AddPepperoni`, `AddBellPeppers`, etc.). To create a new object, we just need to call only the necessary steps for producing a particular configuration of an object.

### **The Director**

We can go further and extract a series of calls to the builder steps used to build a product, into a separate class called th*e director*. The director class defines the order in which to execute the building steps, while the builder provides the implementation of those steps.

Having a director is not necessary. We can always call the building steps in a specific order directly from the client code. However, the director class might be useful for having various construction routines so that they can be reused across the code.

Moreover, the director class hides the details of product construction from the client code. The code only needs to associate a builder with a director, launch the construction, and get the results from the builder.

## Structuring the Builder Pattern

The following diagram represents the different builder parts.

![Builder Schematics](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vgl2agcg0d0bpeob900.png)

The pattern has the following parts:

- **Director**: The *Director* is a class that decides in what steps should the complex class be built. In this example, the name of the complex object is *Product*. It doesn't build the *Product* class directly, but instead, it calls the *IBuilder* interface to create the parts.
- **IBuilder**: The *IBuilder* interface defines all the necessary methods to build a *Product* class. These methods are common to all implementations of the *Builder*. The *Director* calls the *Build* method to get the result of the construction.
- **ConcreteBuilder**: Implements the *IBuilder* interface. It takes a *Product* class and incrementally builds it.
- **Product**: The *Product* object is a complicated class that we need to build.

To demonstrate how the Builder pattern works, we will turn our hungry eyes to one of the best lunch foods: the glorious pizza.

Here's the thing about pizzas: the only thing that defines a pizza is something edible on top of some kind of cooked dough.

That said, different types of pizzas require other steps to make, but they're still just pizzas. Most of the time, the same ingredients can be used to create many different kinds of pizzas. Let's see how we can use the Builder pattern to build some delicious pizzas.

To start off, we will implement the **Director** participant. We'll call our Director class `AssemblyLine`, make it a class, and it will define in what steps the process of making a pizza are called.

```cs
/// 
/// The Director class
/// 
public class AssemblyLine
{
    // Builder uses a complex series of steps
    public void Assemble(PizzaBuilder pizzaBuilder)
    {
        pizzaBuilder.AddDough();
        pizzaBuilder.AddSauce();
        pizzaBuilder.AddCheeses();
        pizzaBuilder.AddMeats();
        pizzaBuilder.AddVeggies();
        pizzaBuilder.AddExtras();
     }
}
```

We also need to define the **Product** participant which is being built by the **Builder** participant. For our example, the **Product** is, of course, a `Pizza`.

```cs
/// 
/// The Product class
/// 
public class Pizza {
  private string pizzaName;
  private Dictionary ingredients =
    new Dictionary();

  public Pizza(string pizzaName) {
    this.pizzaName = pizzaName;
  }

  // Indexer
  public string this[string key] {
    get {
      return ingredients[key];
    }
    set {
      ingredients[key] = value;
    }
  }

  public void Display() {
    Console.WriteLine("\n----------------------------");
    Console.WriteLine($"Pizza: {pizzaName}");

    Console.WriteLine($" Dough: {ingredients["
      dough "]}");
    Console.WriteLine($" Sauce: {ingredients["
      sauce "]}");
    Console.WriteLine($" Meats: {ingredients["
      meats "]}");
    Console.WriteLine($" Cheeses: {ingredients["
      cheeses "]}");
    Console.WriteLine($" Veggies: {ingredients["
      veggies "]}");
    Console.WriteLine($" Extras: {ingredients["
      extras "]}");
  }
}
```

Now that we know the definition of the product we are building, let's create the **Builder** participant. It will be an abstract class named `PizzaBuilder`.

```cs
/// 
/// The Builder Abstract class
/// 
public abstract class PizzaBuilder
{
    protected Pizza pizza;

    // Get the pizza instance
    public Pizza Pizza
    {
        get { return pizza; }
    }

    public abstract void AddDough();
    public abstract void AddSauce();
    public abstract void AddMeats();
    public abstract void AddCheeses();
    public abstract void AddVeggies();
    public abstract void AddExtras();
}
```

Each subclass of PizzaBuilder will need to implement every abstract method to properly build a pizza.

Next, let's implement a few **ConcreteBuilder** classes to build
specific pizzas.

```cs
/// 
/// A ConcreteBuilder class
/// 
class MeatFeastHot : PizzaBuilder
{
    public MeatFeastHot()
    {
        pizza = new Pizza("Meat Feast Hot");
    }

    public override void AddDough()
    {
        pizza["dough"] = "Wheat pizza dough";
    }

    public override void AddSauce()
    {
        pizza["sauce"] = "Tomato base";
    }

    public override void AddMeats()
    {
        pizza["meats"] = "Pepperoni, Ham, Beef, Chicken";
    }

    public override void AddCheeses()
    {
        pizza["cheeses"] = "Signature triple cheese blend, mozzarella";
    }

    public override void AddVeggies()
    {
        pizza["veggies"] = "";
    }

    public override void AddExtras()
    {
        pizza["extras"] = "jalapenos";
    }
}

/// 
/// A ConcreteBuilder class
/// 
class HotNSpicyVeg : PizzaBuilder
{
    public HotNSpicyVeg()
    {
        pizza = new Pizza("Hot 'N' Spicy Veg");
    }

    public override void AddDough()
    {
        pizza["dough"] = "12-grain pizza dough";
    }

    public override void AddSauce()
    {
        pizza["sauce"] = "Tomato base";
    }

    public override void AddMeats()
    {
        pizza["meats"] = "";
    }

    public override void AddCheeses()
    {
        pizza["cheeses"] = "Signature triple cheese blend, mozzarella";
    }

    public override void AddVeggies()
    {
        pizza["veggies"] = "Mushrooms, Peppers, Red Onions";
    }

    public override void AddExtras()
    {
        pizza["extras"] =  "Jalapenos";
    }
}
```

Once we have all our **ConcreteBuilder** classes ready, we can use them in our `Main()` method like so:

```cs
static void Main(string[] args)
{
    PizzaBuilder builder;

    // Create a pizza assembly line
    AssemblyLine shop = new AssemblyLine();

    // Construct and display pizzas
    builder = new MeatFeastHot();
    shop.Assemble(builder);
    builder.Pizza.Display();

    builder = new HotNSpicyVeg();
    shop.Assemble(builder);
    builder.Pizza.Display();

    // Wait for user
    Console.ReadKey();
}
```

The nice thing about this pattern is that we can now reuse the `AssemblyLine` class on any `PizzaBuilder` we wish, and we have more fine-grained control over how the pizzas are built.

## Pros and Cons of Builder Pattern

|                                                                                                                                              |                                                                                                         |
| -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| ✔ We can construct objects in a step-by-step fashion, defer the construction steps, or even run steps recursively.                           | ❌ The overall complexity of the code increases since the pattern requires creating multiple new classes |
| ✔ We can reuse the same construction code when building various representations of the products.                                             |                                                                                                         |
| ✔ We can isolate complex construction code from the business logic of the product, thus satisfying the ***Single Responsibility Principle*** |                                                                                                         |

## Relations with Other Patterns

There are some related patterns to the **Builder**.

-   A lot of designs start as **Factory Methods** (less complicated but
    more customizable than subclassing) and evolve toward **Abstract
    Factories, Prototypes,** or **Builders** (more flexible than
    *Factory Methods* but more complicated)
-   We can use **Builders** when creating complex **Composite** trees.
-   We can combine the **Builder** pattern with the **Bridge** pattern.
    The *director* will play the role of the abstraction, while the
    *builders* will act as implementations
-   **Builders** are often implemented as **Singletons**

## Builder Pattern Variants

### Fluent Builder

Extending the Builder pattern with a fluent API makes it more readable. It also allows us to chain statements for the object configuration. With that, there is no need to specify the builder object with every statement anymore.

```cs
public class FluentPizzaBuilder {
    private readonly Pizza pizza;

    public FluentPizzaBuilder(string pizzaName) {
        pizza = new Pizza(pizzaName);
    }

    public FluentPizzaBuilder WithDough(string dough) {
        pizza["dough"] = dough;
        return this;
    }

    public FluentPizzaBuilder WithSauce(string sauce) {
        pizza["sauce"] = sauce;
        return this;
    }

    public FluentPizzaBuilder WithMeat(string meat) {
        pizza["meats"] = meat;
        return this;
    }

    public FluentPizzaBuilder WithCheese(string cheese) {
        pizza["cheeses"] = cheese;
        return this;
    }

    public FluentPizzaBuilder WithVeggie(string veggie) {
        pizza["veggies"] = veggie;
        return this;
    }

    public FluentPizzaBuilder WithExtra(string extra) {
        pizza["extras"] = extra;
        return this;
    }

    public Pizza Build() {
        return pizza;
    }
}
```

We can now use the Fluent Builder to produce a new Pizza.

```cs
var pizzaBuilder = new FluentPizzaBuilder("Supreme");

var pizzaSupreme = pizzaBuilder
    .WithDough("12-grain pizza dough")
    .WithSauce("Tomato base")
    .WithMeat("Pepperoni, Seasoned Minced Beef, Spicy Pork Sausage")
    .WithVeggie("Mushroom, Mixed Peppers, Red Onions")
    .WithCheese("Mozzarella")
    .WithExtra("Jalapenos")
    .Build();

pizzaSupreme.Display();
```

### Parent-Child Builder

We can use a parent-child relationship with the Builder pattern to
create complex objects. We will first define a parent class tasked to create the complex object and then one or more child classes that create parts of the object.

We need to define some **Products** which will be built by the **Child** builders. For this example, we have 3 products, a **Side** dish, a **Salad** dish and a **Deal** that will contain some Sides and a Salad.

```cs
public class Side
{
    public string Item { get; set; }
    public string Dip { get; set; }
    public string Size { get; set; }
}
```

```cs
public class Salad
{
    public string Base{get;set;}
    public string Veggies{get;set;}
    public string Meats{get;set;}
    public string Cheeses{get;set;}
    public string Dressing{get;set;}
}
```

```cs
public class Deal {
    public List < Side > Sides {
        get;
        set;
    }
    public Salad Salad {
        get;
        set;
    }

    public void Display() {
        foreach(var side in Sides) {
            Console.WriteLine($"Side: {side.Item}");
            Console.WriteLine($"Dip: {side.Dip}");
            Console.WriteLine($"Size: {side.Size}");
            Console.WriteLine();
        }

        Console.WriteLine("Salad:");
        Console.WriteLine($"Base: { Salad.Base}");
        Console.WriteLine($"Veggies: {Salad.Veggies}");
        Console.WriteLine($"Meats: {Salad.Meats}");
        Console.WriteLine($"Cheeses: {Salad.Cheeses}");
        Console.WriteLine($"Dressing: {Salad.Dressing}");
    }
}
```

Then we will have to create a Builder for each of our products. Notice that our **DealBuilder** acts like the *parent* Builder and calls the **SaladBuilder** and the **SideBuilder** that act as the *child* Builders.

```cs
public class DealBuilder
{
    private readonly Deal deal = new Deal();

    public DealBuilder()
    {
        deal.Sides = new List();
    }

    public SaladBuilder AddSalad()
    {
        return new SaladBuilder(this, deal);
    }

    public SideBuilder AddSide()
    {
        return new SideBuilder(this, deal);
    }
    
    public Deal Build()
    {
        return deal;
    }
}
```

```cs
public class SaladBuilder
{
    private readonly DealBuilder _dealBuilder;
    private readonly Deal _deal;
    private readonly Salad _salad = new Salad();

    public SaladBuilder(DealBuilder parentBuilder, Deal deal)
    {
        _dealBuilder = parentBuilder;
        _deal = deal;
    }

    public SaladBuilder WithBase(string saladBase)
    {
        _salad.Base = saladBase;
        return this;
    }

    public SaladBuilder WithVeggies(string veggies)
    {
        _salad.Veggies = veggies;
        return this;
    }

    public SaladBuilder WithMeats(string meats)
    {
        _salad.Meats = meats;
        return this;
    }

    public SaladBuilder WithCheeses(string cheeses)
    {
        _salad.Cheeses = cheeses;
        return this;
    }

    public SaladBuilder WithDressing(string dressing)
    {
        _salad.Dressing = dressing;
        return this;
    }
    
    public DealBuilder BuildSalad()
    {
        _deal.Salad = _salad;
        return _dealBuilder;
    }
}
```

```cs
public class SideBuilder
{
    private DealBuilder dealBuilder;
    private Deal deal;
    private Side side = new Side();

    public SideBuilder(DealBuilder dealBuilder, Deal deal)
    {
        this.dealBuilder = dealBuilder;
        this.deal = deal;
    }

    public SideBuilder WithItem(string item)
    {
        side.Item = item;
        return this;
    }

    public SideBuilder WithDip(string dip)
    {
        side.Dip = dip;
        return this;
    }

    public SideBuilder WithSize(string size)
    {
        side.Size = size;
        return this;
    }
    
    public DealBuilder BuildSide()
    {
        deal.Sides.Add(side);
        return dealBuilder;
    }
}
```

We can now use our Builders to create a Deal object:

```cs
var deal = new DealBuilder()
    .AddSide()
        .WithItem("Spicy Loaded Pepperoni Wedges")
        .WithDip("Mayo")
        .WithSize("Large")
        .BuildSide()
    .AddSide()
        .WithItem("Spicy Cheesy Pepperoni Garlic Bread")
        .WithDip("BBQ Sauce")
        .WithSize("Large")
        .BuildSide()
    .AddSalad()
        .WithBase("Lettuce")
        .WithVeggies("Cherry Tomatoes, Red Cabbage, Carrot")
        .WithDressing("Garlic & Herbs")
        .BuildSalad()
    .Build();
```

Which will create the following complex object:

![Child Builder Object Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/970ofgtoyucww088ub7f.png)

### Progressive Builder

A progressive builder is a variant of the **Builder** pattern. It sequentially uses multiple builders to define a fixed sequence of method-chaining calls. The advantage of this implementation is that ensures that the object is built in the correct order.

In the example below we will create a Pizza Deal, which will have some side dishes, a salad, a pizza, some drinks and a dessert.

As always we will first define our **Product** classes

```cs
public class Side {
    public string Item {
        get;
        set;
    }
    public string Dip {
        get;
        set;
    }
    public string Size {
        get;
        set;
    }

    public void Display() {
        Console.WriteLine("\n--------- Side Dish ---------");
        Console.WriteLine($"Item: {Item}");
        Console.WriteLine($"Dip: {Dip}");
        Console.WriteLine($"Size: {Size}");
    }
}
```

```cs
public class Salad {
    public string Base {
        get;
        set;
    }
    public string Veggies {
        get;
        set;
    }
    public string Meats {
        get;
        set;
    }
    public string Cheeses {
        get;
        set;
    }
    public string Dressing {
        get;
        set;
    }

    public void Display() {
        Console.WriteLine("\n--------- Salad Dish ---------");
        Console.WriteLine($"Base: {Base}");
        Console.WriteLine($"Veggies: {Veggies}");
        Console.WriteLine($"Meats: {Meats}");
        Console.WriteLine($"Cheeses: {Cheeses}");
        Console.WriteLine($"Dressing: {Dressing}");
    }
}
```

```cs
public class Salad {
    public string Base {
        get;
        set;
    }
    public string Veggies {
        get;
        set;
    }
    public string Meats {
        get;
        set;
    }
    public string Cheeses {
        get;
        set;
    }
    public string Dressing {
        get;
        set;
    }

    public void Display() {
        Console.WriteLine("\n--------- Salad Dish ---------");
        Console.WriteLine($"Base: {Base}");
        Console.WriteLine($"Veggies: {Veggies}");
        Console.WriteLine($"Meats: {Meats}");
        Console.WriteLine($"Cheeses: {Cheeses}");
        Console.WriteLine($"Dressing: {Dressing}");
    }
}
```

```cs
 public class Drink {
     public string Item {
         get;
         set;
     }
     public string Size {
         get;
         set;
     }

     public void Display() {
         Console.WriteLine("\n--------- Drink Dish ---------");
         Console.WriteLine($"Item: {Item}");
         Console.WriteLine($"Size: {Size}");
     }
 }
```

```cs
 public class Dessert {
     public string Item {
         get;
         set;
     }
     public string Size {
         get;
         set;
     }

     public void Display() {
         Console.WriteLine("\n--------- Dessert Dish ---------");
         Console.WriteLine($"Item: {Item}");
         Console.WriteLine($"Size: {Size}");
     }
 }
```

And finally the Deal object

```cs
 public class MenuDeal {
     public List < Side > Sides {
         get;
         set;
     }
     public Salad Salad {
         get;
         set;
     }
     public Pizza Pizza {
         get;
         set;
     }
     public Drink Drink {
         get;
         set;
     }
     public Dessert Dessert {
         get;
         set;
     }

     public MenuDeal() {
         Sides = new List < Side > ();
     }

     public void Display() {
         foreach(var side in Sides)
         side.Display();
         Salad.Display();
         Pizza.Display();
         Drink.Display();
         Dessert.Display();
     }
 }
```

Next, we are going to define our Builder objects. Notice that each Builder can call the next builder in the chain.

```cs
public class DessertBuilder {
    private MenuDealBuilder menuDealBuilder;
    private MenuDeal menuDeal;

    private Dessert dessert;

    public DessertBuilder(MenuDealBuilder menuDealBuilder, MenuDeal menuDeal) {
        this.menuDealBuilder = menuDealBuilder;
        this.menuDeal = menuDeal;

        dessert = new Dessert();
    }

    public DessertBuilder WithItem(string item) {
        dessert.Item = item;
        return this;
    }

    public DessertBuilder WithSize(string size) {
        dessert.Size = size;
        return this;
    }

    public MenuDeal Build() {
        menuDeal.Dessert = dessert;
        return menuDeal;
    }
}
```

```cs
public class SideDishBuilder {
    private MenuDealBuilder menuDealBuilder;
    private MenuDeal menuDeal;

    private Side sideDish;

    public SideDishBuilder(MenuDealBuilder menuDealBuilder, MenuDeal menuDeal) {
        this.menuDealBuilder = menuDealBuilder;
        this.menuDeal = menuDeal;
        sideDish = new Side();
    }

    public SideDishBuilder WithItem(string item) {
        sideDish.Item = item;
        return this;
    }

    public SideDishBuilder WithDip(string dip) {
        sideDish.Dip = dip;
        return this;
    }

    public SideDishBuilder WithSize(string size) {
        sideDish.Size = size;
        return this;
    }

    public SideDishBuilder AddSideDish() {
        menuDeal.Sides.Add(sideDish);
        return new SideDishBuilder(menuDealBuilder, menuDeal);
    }

    public SaladBuilder AddSaladDish() {
        menuDeal.Sides.Add(sideDish);
        return new SaladBuilder(menuDealBuilder, menuDeal);
    }
}
```

```cs
using ProgressiveBuilder.Products;

namespace ProgressiveBuilder.Builders {
    public class SaladBuilder {
        private MenuDealBuilder menuDealBuilder;
        private MenuDeal menuDeal;

        private Salad salad;

        public SaladBuilder(MenuDealBuilder menuDealBuilder, MenuDeal menuDeal) {
            this.menuDealBuilder = menuDealBuilder;
            this.menuDeal = menuDeal;

            salad = new Salad();
        }

        public SaladBuilder WithBase(string saladBase) {
            salad.Base = saladBase;
            return this;
        }

        public SaladBuilder WithVeggies(string veggies) {
            salad.Veggies = veggies;
            return this;
        }

        public SaladBuilder WithMeats(string meats) {
            salad.Meats = meats;
            return this;
        }

        public SaladBuilder WithCheeses(string cheeses) {
            salad.Cheeses = cheeses;
            return this;
        }

        public SaladBuilder WithDressing(string dressing) {
            salad.Dressing = dressing;
            return this;
        }

        public PizzaBuilder AddPizzaDish() {
            menuDeal.Salad = salad;
            return new PizzaBuilder(menuDealBuilder, menuDeal);
        }
    }
}
```

```cs
public class PizzaBuilder
    {
        private MenuDealBuilder menuDealBuilder;
        private MenuDeal menuDeal;

        private Pizza pizza;

        public PizzaBuilder(MenuDealBuilder menuDealBuilder, MenuDeal menuDeal)
        {
            this.menuDealBuilder = menuDealBuilder;
            this.menuDeal = menuDeal;

            pizza = new Pizza();
        }

        public PizzaBuilder WithDough(string dough)
        {
            pizza.Dough = dough;
            return this;
        }

        public PizzaBuilder WithSauce(string sauce)
        {
            pizza.Sauce = sauce;
            return this;
        }

        public PizzaBuilder WithCheeses(string cheeses)
        {
            pizza.Cheeses = cheeses;
            return this;
        }

        public PizzaBuilder WithMeats(string meats)
        {
            pizza.Meats = meats;
            return this;
        }

        public PizzaBuilder WithVeggies(string veggies)
        {
            pizza.Veggies = veggies;
            return this;
        }

        public PizzaBuilder WithExtras(string extras)
        {
            pizza.Extras = extras;
            return this;
        }

        public DrinkBuilder AddDrink()
        {
            menuDeal.Pizza = pizza;
            return new DrinkBuilder(menuDealBuilder, menuDeal);
        }
    }
```

```cs
public class DrinkBuilder {
    private MenuDealBuilder dealBuilder;
    private MenuDeal menuDeal;

    private Drink drink;

    public DrinkBuilder(MenuDealBuilder dealBuilder, MenuDeal menuDeal) {
        this.dealBuilder = dealBuilder;
        this.menuDeal = menuDeal;

        drink = new Drink();
    }

    public DrinkBuilder WithItem(string item) {
        drink.Item = item;
        return this;
    }

    public DrinkBuilder WithSize(string size) {
        drink.Size = size;
        return this;
    }

    public DessertBuilder AddDesert() {
        menuDeal.Drink = drink;
        return new DessertBuilder(dealBuilder, menuDeal);
    }
}
```

```cs
public class DessertBuilder {
    private MenuDealBuilder menuDealBuilder;
    private MenuDeal menuDeal;

    private Dessert dessert;

    public DessertBuilder(MenuDealBuilder menuDealBuilder, MenuDeal menuDeal) {
        this.menuDealBuilder = menuDealBuilder;
        this.menuDeal = menuDeal;

        dessert = new Dessert();
    }

    public DessertBuilder WithItem(string item) {
        dessert.Item = item;
        return this;
    }

    public DessertBuilder WithSize(string size) {
        dessert.Size = size;
        return this;
    }

    public MenuDeal Build() {
        menuDeal.Dessert = dessert;
        return menuDeal;
    }
}
```

The final step is to call the chain of builders to create a deal object:

```cs
var menuBuilder = new MenuDealBuilder();
var menu = menuBuilder
    .AddSideDish()
        .WithItem("Breaded All-White Chicken Breast, Baked in Stone Oven")
        .WithDip("Frank's Spicy Buffalo")
        .WithSize("Large")
    .AddSideDish()
        .WithItem("Gluten Free Corn Tortilla Chips")
        .WithDip("Guacamole")
        .WithSize("Large")
    .AddSaladDish()
        .WithBase("Fresh Mixed Lettuce")
        .WithVeggies("Chopped Onions, Green Bell Peppers, Black Olives, Mushrooms")
        .WithMeats("Fajita Chicken, Bacon Bits")
        .WithCheeses("Mozzarella")
        .WithDressing("Zesty Italian")
    .AddPizzaDish()
        .WithDough("Sourdough with Cream Cheese Crust")
        .WithSauce("Tomato Sauce")
        .WithMeats("Beef, Sausage, Pepperoni")
        .WithVeggies("Mushrooms, Green Bell Peppers, Onions")
        .WithCheeses("Mozzarella")
    .AddDrink()
        .WithItem("Soda")
        .WithSize("Large")
    .AddDesert()
        .WithItem("Cookie Dough Ice Cream")
        .WithSize("Large")
    .Build();

menu.Display();
```

Each **Builder** will create its own part of the **Deal** object, and then will call the next builder in the chain. This will ensure that the parts will be created in the correct order.

The above will create this complex object:


![Progressive Builder Object Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihzmy44839xq0cc9lgzq.png)

## Final Thoughts

In this article, we have discussed what is the builder pattern, when to use it and what are the pros and cons of using this design pattern. We then discussed how the Builder pattern relates to other classic design patterns. Finally, we saw some variations of the Builder pattern that either improve the readability of the pattern (*FluentBuilder*) or address a specific issue.

It's worth noting that the Builder pattern, along with the rest of the design patterns presented by the Gang of Four, is not a panacea or a be-all-end-all solution when designing an application. Once again it's up to the engineers to consider when to use a specific pattern. After all these patterns are useful when used as a precision tool, not a sledgehammer.