पाठ 6 / 25
Builder
Assemble complex objects step by step.
Readable construction
Intent: separate the construction of a complex object from its representation, so it can be built step by step and validated before use. Builders shine when an object has many optional parts, ordering rules or validation: HTTP requests, SQL queries, test data, email messages. A fluent builder returns this from each step so calls chain. Use it when a constructor would need many optional parameters (the "telescoping constructor" smell) or when construction needs validation. Avoid it when an options object is enough: in TypeScript and Python, named/optional parameters or an object literal with defaults often replace a builder entirely. Builders remain idiomatic in Java, where there are no named arguments.
An email builder
Validates before producing an immutable message.
interface Email {
readonly to: string[];
readonly subject: string;
readonly html: string;
readonly cc: string[];
readonly attachments: { name: string; data: Uint8Array }[];
}
class EmailBuilder {
private to: string[] = [];
private cc: string[] = [];
private subject = '';
private html = '';
private attachments: Email['attachments'] = [];
addTo(address: string) { this.to.push(address); return this; }
addCc(address: string) { this.cc.push(address); return this; }
withSubject(s: string) { this.subject = s; return this; }
withHtml(h: string) { this.html = h; return this; }
attach(name: string, data: Uint8Array) { this.attachments.push({ name, data }); return this; }
build(): Email {
if (this.to.length === 0) throw new Error('At least one recipient is required');
if (!this.subject) throw new Error('Subject is required');
return Object.freeze({ to: [...this.to], cc: [...this.cc], subject: this.subject,
html: this.html, attachments: [...this.attachments] });
}
}
const email = new EmailBuilder()
.addTo('asha@example.com')
.withSubject('Your invoice')
.withHtml('<p>Thanks for your order.</p>')
.attach('invoice.pdf', pdfBytes)
.build();Builders are great for test data
A test-data builder with sensible defaults lets each test override only the fields it cares about, for example aUser().withRole('admin').build(), which keeps tests short and intention-revealing.
त्वरित जाँच: In TypeScript, what often replaces a simple builder?
- A Visitor
- A Singleton
- An Observer
- An options object with defaults
Answer
An options object with defaults — Object literals give named, optional parameters.