update on 5 min read
Builder Design patterns
Here, I will exaplin about builder design pattern.
Intro
The Builder design pattern is a creational pattern that makes it easier to create complex objects by breaking down the process into simple, manageable steps. It helps developers build objects step by step, which makes the code cleaner and easier to maintain—especially when writing unit tests. Basically, the Builder pattern offers a single class with easy-to-use methods that the client can call. Behind the scenes, it takes care of the complex work, so you don’t have to. This approach separates the object’s construction from how it’s represented, letting both parts change independently without affecting each other. In cloud and data engineering, the Builder pattern is super useful for creating flexible and maintainable systems. It helps you set up your unit test layers smoothly by keeping things organized. To put it simply: the Builder pattern allows you to build complicated objects step by step, making the whole process straightforward and easier to manage.
Core components in Builder Design Pattern
- Product -> the complex object being build
- Builder -> abstract/ blue print for building objects
- Concrete Builder -> implementation of the builder interface to build
- Director -> its a optional
Types of builder
- Simple Builder: Used when the object has a fixed structure but needs a clean way to construct it.
- Fluent Builder: Uses method chaining for a more readable and expressive syntax.
- Generic Builder: Uses generics to build different types of objects with reusable logic.
- Nested Builder: Useful for building hierarchical or nested objects like HTML or UI components.
Which Solid Priciple implemented in this Pattern?
- The Pattern primarily implemented Single Responsiablity Prinples (SRP)
- Each component is implemented to have single responsibility
- its encourage the Open and close Principle (OCP).
- means with interface we can extends it behaviour
UML Diagram

Simple Builder
- Straightforward separation of construction logic.
- No Method Chaining.
Component | Role | Example |
---|---|---|
Builder | Defines steps | IReportBuilder |
ConcreteBuilder | Actual implementation of steps | ExcelReportBuilder |
Product | The complex object being created | Report |
Director | Controls construction process (optional) | ReportDirector |
Client | Initiates the build (uses above classes) | Your method Main |
Example for Simple Builder
In this exaplme , I’m creating reports (either Excel or PDF) with a header, content, and footer. Each report type is built in a slightly different way, but the steps (setting header, content, footer, etc.) are the same.
public class Report{ public string ReportType { get; set; } public string ReportHeader { get; set; } public string ReportContent { get; set; } public string ReportFooter { get; set; }
public void DisplayReport() { Console.WriteLine($"Report Type: {ReportType}"); Console.WriteLine($"Header: {ReportHeader}"); Console.WriteLine($"Content: {ReportContent}"); Console.WriteLine($"Footer: {ReportFooter}"); }}
Builder Interface ()IReportBuilder
- Defines the steps needed to build a report: , , , and .
SetHeader``SetContent``SetFooter``GetReport
public interface IReportBuilder{ void SetHeader(string header); void SetContent( string content); void SetFooter( string footer); Report GetReport();}
Concrete Builders PdfReportBuilder
- Implement these steps to build specific representations (Excel or PDF).
public class ExcelReportBuilder : IReportBuilder{ private readonly Report _report = new(); public void SetHeader(string header) => _report.ReportHeader = header;
public void SetContent(string content) => _report.ReportContent = content;
public void SetFooter(string footer) => _report.ReportFooter = footer; public Report GetReport() { _report.ReportType = "Excel"; return _report; }}
Concrete Builders ExcelReportBuilder
- Implement these steps to build specific representations (Excel or PDF).
public class PdfReportBuilder : IReportBuilder{ private readonly Report _report = new();
public void SetHeader(string header) => _report.ReportHeader = header;
public void SetContent(string content) => _report.ReportContent = content;
public void SetFooter(string footer) => _report.ReportFooter = footer;
public Report GetReport() { _report.ReportType = "PDF"; return _report; }}
Director ()ReportDirector
- Knows the order in which to call the building steps.
- Gets a builder and tells it what to build.
public class ReportDirector(IReportBuilder builder){ public Report GetReport(string header, string content, string footer) { builder.SetHeader(header); builder.SetContent(content); builder.SetFooter(footer); return builder.GetReport(); }}
Main ()calling without Director
internal static class Program{ private static void Main(string[] args) { IReportBuilder excelBuilder = new ExcelReportBuilder(); excelBuilder.SetHeader("Excel Header"); excelBuilder.SetContent("Excel Content"); excelBuilder.SetFooter("Excel Footer"); excelBuilder.GetReport().DisplayReport();
Console.WriteLine();
IReportBuilder pdfBuilder = new PdfReportBuilder(); pdfBuilder.SetHeader("PDF Header"); pdfBuilder.SetContent("PDF Content"); pdfBuilder.SetFooter("PDF Footer"); pdfBuilder.GetReport().DisplayReport(); }}
Main ()calling with Director
internal static class Program{ private static void Main(string[] args) { IReportBuilder excelBuilder = new ExcelReportBuilder(); Console.WriteLine("With Director \n" ); var director = new ReportDirector(excelBuilder); director.GetReport("Excel Header", "Excel Content", "Excel Footer").DisplayReport();
Console.WriteLine();
director = new ReportDirector(pdfBuilder); director.GetReport("PDF Header", "PDF Content", "PDF Footer").DisplayReport();
}}
Fluent Builder
The key feature is method chaining, where each method returns the builder object itself (return this), allowing calls to be linked in a single statement.
Fluent Pattern Feature | In Your Example |
---|---|
Method chaining | SetHeader().SetContent().SetFooter() |
Enhanced readability | Code reads like instructions |
Builder returns self-reference | Each Set...() returns builder |
Final method for result | .Build() creates the report |
Example for Fluent Builder
- Each method returns the instance of the builder itself, so you can immediately call the next setup method
public class ExcelReportBuilder
{ private readonly Report _report = new();
public ExcelReportBuilder SetHeader(string header) { _report.ReportHeader = header; return this; }
public ExcelReportBuilder SetContent(string content) { _report.ReportContent = content; return this; }
public ExcelReportBuilder SetFooter(string footer) { _report.ReportFooter = footer; return this; }
public Report Build() { _report.ReportType = "PDF"; return _report; }
}
- Here, I have create a
ExcelReportBuilder
instance. - Methods like
.SetHeader(...)
,.SetContent(...)
, and.SetFooter(...)
are called one after another. .Build()
at the end constructs the final report object.
var excelReport = new ExcelReportBuilder() .SetHeader("Excel Header") .SetContent("Excel Content") .SetFooter("Excel Footer") .Build();
excelReport.DisplayReport();
Generic Builder
The key feature is Reusable logic for building different types.
Example for Generic Builder
I have code that builds a object using a generic builder: Report
Instantiating the Builder
new GenericBuilder<Report>()
creates a new builder for the type.Report
Chaining Set Operations
.Set(report => report.Property = value)
adds a configuration step for each property:- This uses a lambda expression to set the property value.
- Each call returns the builder itself, enabling method chaining.
public class GenericBuilder<T> where T : new(){ private T _instance = new(); public GenericBuilder<T> Set(Action<T> setter) { setter(_instance); return this; } public T Build() => _instance;}
Building the Object
.Build()
finally creates the configured instance.Report
Using the Result
excalReport.DisplayReport();
makes use of the fully configured report.
internal static class Program{ private static void Main(string[] args) {
var excalReport= new GenericBuilder<Report>() .Set(report => report.ReportType = "Excel") .Set(report => report.ReportHeader = "Excel Header") .Set(report => report.ReportContent = "Excel Content") .Set(report => report.ReportFooter = "Excel Footer") .Build();
excalReport.DisplayReport();
}}