Creational Patterns • Builder PatternMedium⏱️ ~2 min
Builder Pattern: Structure and Participants
The Builder pattern involves four key participants that collaborate to construct complex objects in a controlled manner.
Product
- field1: Type
- field2: Type
- optionalField: Type
- field2: Type
- optionalField: Type
+ getField1(): Type
+ getField2(): Type
+ getField2(): Type
▲
Builder
- product: Product
- field1: Type
- field2: Type
- field1: Type
- field2: Type
+ Builder(required)
+ setField2(value): Builder
+ setOptional(value): Builder
+ build(): Product
+ setField2(value): Builder
+ setOptional(value): Builder
+ build(): Product
◆
Director (Optional)
- builder: Builder
+ construct(): void
+ getResult(): Product
+ getResult(): Product
Participant Responsibilities:
Product: The complex object being constructed. Contains private fields and provides only getters to enforce immutability. Does NOT have public setters. All fields are set through a private or package-private constructor that accepts the builder as a parameter.
Builder: Provides methods to set each attribute of the product. The builder constructor accepts required parameters, ensuring they cannot be omitted. Optional parameters are set through fluent setter methods that return
ConcreteBuilder: In languages without nested classes, you might have separate builder implementations for different product variations. However, the most common LLD approach uses a static nested builder class within the product itself, giving it access to the product's private constructor.
Director (Optional): Encapsulates a specific construction sequence. Directors are useful when you have standard configurations that are frequently constructed. For example, a
Product: The complex object being constructed. Contains private fields and provides only getters to enforce immutability. Does NOT have public setters. All fields are set through a private or package-private constructor that accepts the builder as a parameter.
Builder: Provides methods to set each attribute of the product. The builder constructor accepts required parameters, ensuring they cannot be omitted. Optional parameters are set through fluent setter methods that return
this for method chaining. The build() method performs validation and constructs the immutable product.ConcreteBuilder: In languages without nested classes, you might have separate builder implementations for different product variations. However, the most common LLD approach uses a static nested builder class within the product itself, giving it access to the product's private constructor.
Director (Optional): Encapsulates a specific construction sequence. Directors are useful when you have standard configurations that are frequently constructed. For example, a
StandardRoomDirector might configure a builder with typical settings, while a LuxuryRoomDirector sets premium options. Directors are NOT required for the pattern, most implementations let clients call builder methods directly.Design Decision: Should Builder be a nested class or separate? Nested gives access to private constructors without package-level visibility. Separate allows builders to be reused across product hierarchies. For interviews, nested is the standard approach unless you need flexibility to build multiple related products.
Key Relationships:
Composition (◆): Builder HAS-A Product under construction. The builder accumulates state and creates the product at the end.
Dependency: Product depends on Builder for construction but not afterward. Once built, the product is independent.
Association: Director (if used) associates with Builder to orchestrate construction steps.
Composition (◆): Builder HAS-A Product under construction. The builder accumulates state and creates the product at the end.
Dependency: Product depends on Builder for construction but not afterward. Once built, the product is independent.
Association: Director (if used) associates with Builder to orchestrate construction steps.
💡 Key Takeaways
✓Product is the complex object with private fields and no public setters
✓Builder provides fluent methods returning 'this' for method chaining
✓Required parameters go in builder constructor, optional via setter methods
✓build() method validates state and creates immutable product
✓Director is optional, encapsulates common construction sequences
📌 Examples
1Query builder constructs SQL statements step by step
2Document builder assembles sections, headers, footers incrementally
3Configuration builder sets up complex application configurations