The Builder pattern is a creational design pattern that separates the construction of a complex object from its representation. It allows the same construction process to create different representations of an object.
Core Intent
“Separate the construction of a complex object from its representation so that the same construction process can create different representations.”
This enables step-by-step construction of objects while keeping the final product flexible and reusable.
When to Use Builder
| Scenario | Use Case |
|---|---|
| Object has many optional parameters | Avoid telescoping constructors |
| Construction involves multiple steps | Ensure valid intermediate states |
| Need different representations of same data | e.g., HTML vs JSON vs XML |
| Construction logic is complex or conditional | Encapsulate in steps |
| Want immutable final objects | Build then seal |
Avoid when:
- Object is simple → Direct constructor suffices
- Performance is critical → Slight overhead
Where It Is Used in Real Systems
| Domain | Example |
|---|---|
| UI Rendering | Generating HTML, PDF, or plain text reports |
| Document Generation | Word, PDF, Markdown exporters |
| Query Building | SQL SELECT … WHERE … ORDER BY |
| Configuration Objects | HttpClient with headers, timeout, auth |
| Game Entity Creation | Character with stats, inventory, skills |
Key Benefits
- Step-by-step construction
- Reusability of construction logic
- Immutability of final product
- Readability via fluent API
- Validation at build time
The Builder pattern is a creational design pattern that separates the construction of a complex object from its representation. It allows the same construction process to create different representations of an object.
Core Intent
“Separate the construction of a complex object from its representation so that the same construction process can create different representations.”
This enables step-by-step construction of objects while keeping the final product flexible and reusable.
When to Use Builder
| Scenario | Use Case |
|---|---|
| Object has many optional parameters | Avoid telescoping constructors |
| Construction involves multiple steps | Ensure valid intermediate states |
| Need different representations of same data | e.g., HTML vs JSON vs XML |
| Construction logic is complex or conditional | Encapsulate in steps |
| Want immutable final objects | Build then seal |
Avoid when:
- Object is simple → Direct constructor suffices
- Performance is critical → Slight overhead
Where It Is Used in Real Systems
| Domain | Example |
|---|---|
| UI Rendering | Generating HTML, PDF, or plain text reports |
| Document Generation | Word, PDF, Markdown exporters |
| Query Building | SQL SELECT … WHERE … ORDER BY |
| Configuration Objects | HttpClient with headers, timeout, auth |
| Game Entity Creation | Character with stats, inventory, skills |
Key Benefits
- Step-by-step construction
- Reusability of construction logic
- Immutability of final product
- Readability via fluent API
- Validation at build time
Real-World Example: E-Commerce Order Receipt Generator
An e-commerce platform generates order receipts in multiple formats:
- HTML (for email)
- Plain Text (for SMS/console)
- PDF (for downloadable invoice)
Each receipt includes:
- Header (store name, date)
- Customer info
- Order items (with price, qty, subtotal)
- Tax & shipping
- Total
- Footer (thank you, terms)
We want:
- Same data → different output formats
- Clean, readable construction
- Extensible to new formats (JSON, XML, etc.)
C# Implementation
using System;
using System.Collections.Generic;
using-System.Text;
// ==================== PRODUCT ====================
public class OrderReceipt
{
public string StoreName { get; private set; }
public DateTime OrderDate { get; private set; }
public string CustomerName { get; private set; }
public string CustomerEmail { get; private set; }
public List<OrderItem> Items { get; private set; } = new();
public decimal Tax { get; private set; }
public decimal Shipping { get; private set; }
public decimal Total => Items.Sum(i => i.Subtotal) + Tax + Shipping;
public string FooterNote { get; private set; }
// Internal constructor — only Builder can create
internal OrderReceipt() { }
public class OrderItem
{
public string Name { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Subtotal => Quantity * UnitPrice;
}
// For debugging / display
public override string ToString()
=> $"Receipt[Items={Items.Count}, Total={Total:C}]";
}
// ==================== BUILDER INTERFACE ====================
public interface IReceiptBuilder
{
IReceiptBuilder SetStoreInfo(string name, DateTime date);
IReceiptBuilder SetCustomer(string name, string email);
IReceiptBuilder AddItem(string name, int qty, decimal price);
IReceiptBuilder SetTax(decimal tax);
IReceiptBuilder SetShipping(decimal shipping);
IReceiptBuilder SetFooter(string note);
OrderReceipt Build();
string GetResult(); // Final formatted string
}
// ==================== CONCRETE BUILDERS ====================
public class HtmlReceiptBuilder : IReceiptBuilder
{
private readonly OrderReceipt _receipt = new();
private readonly StringBuilder _html = new();
public IReceiptBuilder SetStoreInfo(string name, DateTime date)
{
_receipt.StoreName = name;
_receipt.OrderDate = date;
return this;
}
public IReceiptBuilder SetCustomer(string name, string email)
{
_receipt.CustomerName = name;
_receipt.CustomerEmail = email;
return this;
}
public IReceiptBuilder AddItem(string name, int qty, decimal price)
{
_receipt.Items.Add(new OrderReceipt.OrderItem
{
Name = name,
Quantity = qty,
UnitPrice = price
});
return this;
}
public IReceiptBuilder SetTax(decimal tax)
{
_receipt.Tax = tax;
return this;
}
public IReceiptBuilder SetShipping(decimal shipping)
{
_receipt.Shipping = shipping;
return this;
}
public IReceiptBuilder SetFooter(string note)
{
_receipt.FooterNote = note;
return this;
}
public OrderReceipt Build()
{
GenerateHtml();
return _receipt;
}
public string GetResult() => _html.ToString();
private void GenerateHtml()
{
_html.AppendLine("<!DOCTYPE html><html><body>");
_html.AppendLine($"<h1>{_receipt.StoreName}</h1>");
_html.AppendLine($"<p>Date: {_receipt.OrderDate:yyyy-MM-dd}</p>");
_html.AppendLine($"<p>Customer: {_receipt.CustomerName} ({_receipt.CustomerEmail})</p>");
_html.AppendLine("<table border='1'><tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr>");
foreach (var item in _receipt.Items)
{
_html.AppendLine($"<tr><td>{item.Name}</td><td>{item.Quantity}</td><td>{item.UnitPrice:C}</td><td>{item.Subtotal:C}</td></tr>");
}
_html.AppendLine("</table>");
_html.AppendLine($"<p>Tax: {_receipt.Tax:C}</p>");
_html.AppendLine($"<p>Shipping: {_receipt.Shipping:C}</p>");
_html.AppendLine($"<p><strong>Total: {_receipt.Total:C}</strong></p>");
_html.AppendLine($"<footer>{_receipt.FooterNote}</footer>");
_html.AppendLine("</body></html>");
}
}
public class TextReceiptBuilder : IReceiptBuilder
{
private readonly OrderReceipt _receipt = new();
private readonly StringBuilder _text = new();
public IReceiptBuilder SetStoreInfo(string name, DateTime date)
{
_receipt.StoreName = name;
_receipt.OrderDate = date;
return this;
}
public IReceiptBuilder SetCustomer(string name, string email)
{
_receipt.CustomerName = name;
_receipt.CustomerEmail = email;
return this;
}
public IReceiptBuilder AddItem(string name, int qty, decimal price)
{
_receipt.Items.Add(new OrderReceipt.OrderItem
{
Name = name,
Quantity = qty,
UnitPrice = price
});
return this;
}
public IReceiptBuilder SetTax(decimal tax)
{
_receipt.Tax = tax;
return this;
}
public IReceiptBuilder SetShipping(decimal shipping)
{
_receipt.Shipping = shipping;
return this;
}
public IReceiptBuilder SetFooter(string note)
{
_receipt.FooterNote = note;
return this;
}
public OrderReceipt Build()
{
GenerateText();
return _receipt;
}
public string GetResult() => _text.ToString();
private void GenerateText()
{
_text.AppendLine($"{_receipt.StoreName}");
_text.AppendLine($"Date: {_receipt.OrderDate:yyyy-MM-dd}");
_text.AppendLine($"Customer: {_receipt.CustomerName} <{_receipt.CustomerEmail}>");
_text.AppendLine(new string('-', 50));
foreach (var item in _receipt.Items)
{
_text.AppendLine($"{item.Name.PadRight(25)} {item.Quantity,3} x {item.UnitPrice,8:C} = {item.Subtotal,10:C}");
}
_text.AppendLine(new string('-', 50));
_text.AppendLine($"Tax: {_receipt.Tax,38:C}");
_text.AppendLine($"Shipping: {_receipt.Shipping,38:C}");
_text.AppendLine($"TOTAL: {_receipt.Total,38:C}");
_text.AppendLine(_receipt.FooterNote);
}
}
// Optional: PDF Builder (simplified)
public class PdfReceiptBuilder : IReceiptBuilder
{
private readonly OrderReceipt _receipt = new();
private string _pdfPath;
// Same fluent methods...
public IReceiptBuilder SetStoreInfo(string name, DateTime date) { _receipt.StoreName = name; _receipt.OrderDate = date; return this; }
public IReceiptBuilder SetCustomer(string name, string email) { _receipt.CustomerName = name; _receipt.CustomerEmail = email; return this; }
public IReceiptBuilder AddItem(string name, int qty, decimal price) { _receipt.Items.Add(new OrderReceipt.OrderItem { Name = name, Quantity = qty, UnitPrice = price }); return this; }
public IReceiptBuilder SetTax(decimal tax) { _receipt.Tax = tax; return this; }
public IReceiptBuilder SetShipping(decimal shipping) { _receipt.Shipping = shipping; return this; }
public IReceiptBuilder SetFooter(string note) { _receipt.FooterNote = note; return this; }
public OrderReceipt Build()
{
GeneratePdf();
return _receipt;
}
public string GetResult() => _pdfPath;
private void GeneratePdf()
{
_pdfPath = $"receipt_{Guid.NewGuid():N}.pdf";
Console.WriteLine($"[PDF] Generated: {_pdfPath} (simulated)");
}
}
// ==================== DIRECTOR ====================
public class ReceiptDirector
{
public void ConstructStandardReceipt(IReceiptBuilder builder, OrderData data)
{
builder
.SetStoreInfo("GlobalMart", data.OrderDate)
.SetCustomer(data.CustomerName, data.CustomerEmail)
.SetTax(data.Tax)
.SetShipping(data.Shipping)
.SetFooter("Thank you for shopping with us!");
foreach (var item in data.Items)
{
builder.AddItem(item.name, item.quantity, item.price);
}
}
}
public class OrderData
{
public DateTime OrderDate { get; set; }
public string CustomerName { get; set; }
public string CustomerEmail { get; set; }
public decimal Tax { get; set; }
public decimal Shipping { get; set; }
public List<(string name, int quantity, decimal price)> Items { get; set; } = new();
}
// ==================== CLIENT / DEMO ====================
class Program
{
static void Main()
{
var order = new OrderData
{
OrderDate = DateTime.Now,
CustomerName = "Alice Johnson",
CustomerEmail = "alice@example.com",
Tax = 12.50m,
Shipping = 5.99m,
Items = new List<(string, int, decimal)>
{
("Laptop", 1, 999.00m),
("Mouse", 2, 25.00m),
("Keyboard", 1, 75.00m)
}
};
var director = new ReceiptDirector();
Console.WriteLine("=== HTML RECEIPT ===");
var htmlBuilder = new HtmlReceiptBuilder();
director.ConstructStandardReceipt(htmlBuilder, order);
Console.WriteLine(htmlBuilder.GetResult());
Console.WriteLine("\n=== TEXT RECEIPT ===");
var textBuilder = new TextReceiptBuilder();
director.ConstructStandardReceipt(textBuilder, order);
Console.WriteLine(textBuilder.GetResult());
Console.WriteLine("=== PDF RECEIPT ===");
var pdfBuilder = new PdfReceiptBuilder();
director.ConstructStandardReceipt(pdfBuilder, order);
Console.WriteLine($"PDF saved at: {pdfBuilder.GetResult()}");
}
}Sample Output
=== HTML RECEIPT ===
<!DOCTYPE html><html><body>
<h1>GlobalMart</h1>
<p>Date: 2025-04-05</p>
<p>Customer: Alice Johnson (alice@example.com)</p>
<table border='1'><tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr>
<tr><td>Laptop</td><td>1</td><td>$999.00</td><td>$999.00</td></tr>
...
=== TEXT RECEIPT ===
GlobalMart
Date: 2025-04-05
Customer: Alice Johnson <alice@example.com>
--------------------------------------------------
Laptop 1 x $999.00 = $999.00
Mouse 2 x $25.00 = $50.00
Keyboard 1 x $75.00 = $75.00
--------------------------------------------------
Tax: $12.50
Shipping: $5.99
TOTAL: $1,142.49
Thank you for shopping with us!
=== PDF RECEIPT ===
[PDF] Generated: receipt_a1b2c3d4e5.pdf (simulated)
PDF saved at: receipt_a1b2c3d4e5.pdfParticipants in the Builder Pattern
The classes and objects participating in this pattern include:
- Product (OrderReceipt)
- The complex object being being constructed.
- Usually immutable.
- Builder (IReceiptBuilder)
- Declares a common construction interface for all steps.
- ConcreteBuilder (HtmlReceiptBuilder, TextReceiptBuilder, PdfReceiptBuilder)
- Implements the builder interface.
- Provides specific implementation for each step.
- Maintains the intermediate product.
- Returns the final product.
- Director (ReceiptDirector)
- Orchestrates the construction steps using a Builder instance.
- Optional — client can call builder directly.
- Client
- Configures the Director or calls Builder steps directly.
- Chooses which ConcreteBuilder to use.
UML Class Diagram

Summary Table
| Participant | Role in E-Commerce Receipt |
|---|---|
| Product | OrderReceipt – final immutable receipt |
| Builder | IReceiptBuilder – common steps |
| ConcreteBuilder | HtmlReceiptBuilder, TextReceiptBuilder, PdfReceiptBuilder |
| Director | ReceiptDirector – reusable construction logic |
| Client | Program – selects format and triggers build |
Advantages in E-Commerce
| Benefit | Impact |
|---|---|
| Fluent API | builder.AddItem(…).SetTax(…) |
| Reusable Logic | Director handles standard flow |
| Extensible | Add JsonReceiptBuilder easily |
| Testable | Mock IReceiptBuilder |
| Clean Code | No 10-parameter constructors |
Conclusion
The Builder pattern is perfect for generating multi-format documents like receipts, invoices, or reports in e-commerce. It provides:
- Clarity in construction
- Flexibility in output
- Maintainability across formats
Used by frameworks like iText (PDF), Razor Templates (HTML), and StringBuilder patterns in .NET.




