โ† Back to Design Patterns
๐Ÿ”จ
Creational

Builder

Constructs complex objects step by step using a fluent interface, separating construction from representation.

The Problem

A class with many optional parameters leads to telescoping constructors or long init calls that are hard to read. You need a clean way to build objects incrementally.

How It Works

  • โ€บMethod chaining (fluent interface) makes construction readable
  • โ€บSame builder can produce different representations
  • โ€บValidates required fields only at build() time
  • โ€บImmutable result: once built, the object is complete
  • โ€บAvoids the "telescoping constructor" anti-pattern

When to Use

โœ“Objects with many optional or configurable fields
โœ“When the object requires multi-step construction
โœ“When you want to create different configurations of the same object type
โœ“HTTP request builders, query builders, notification payloads

Real-World Examples

๐ŸŽ
iOS

URLComponents, NSAttributedString, UIAlertController + addAction calls

๐Ÿค–
Android

AlertDialog.Builder, Notification.Builder, OkHttpClient.Builder

๐ŸŒ
Web

URLSearchParams, axios config, Knex/TypeORM query builders

Code Examples

Swift
struct PushPayload {
    let title: String
    let body: String
    let badge: Int
    let sound: String
    let category: String?
}

final class PushPayloadBuilder {
    private var title = ""
    private var body  = ""
    private var badge = 0
    private var sound = "default"
    private var category: String?

    func title(_ v: String)    -> Self { title    = v; return self }
    func body(_ v: String)     -> Self { body     = v; return self }
    func badge(_ v: Int)       -> Self { badge    = v; return self }
    func sound(_ v: String)    -> Self { sound    = v; return self }
    func category(_ v: String) -> Self { category = v; return self }

    func build() -> PushPayload {
        PushPayload(title: title, body: body, badge: badge,
                    sound: sound, category: category)
    }
}

let payload = PushPayloadBuilder()
    .title("New Message")
    .body("You have 3 unread messages")
    .badge(3)
    .category("MESSAGE")
    .build()