← Back to Advanced Java Course | Chapter 6: Design Patterns | Lesson 5 of 14

Java का Builder Pattern

Builder pattern किसी जटिल object को step by step बनाता है, जैसे सिर्फ पसंदीदा toppings के साथ burger assemble करना। यह कई options होने पर code को readable रखता है।
Syntax
java
Product product = new Product.Builder()
    .setPart1(value1)
    .setPart2(value2)
    .build();

Why Use Builder Pattern?

Builder pattern जटिल objects को एक साथ के बजाय step by step बनाता है, और यह सीधे 'telescoping constructor' समस्या को हल करता है, जहां किसी class में optional parameters के हर combination को support करने के लिए overloaded constructors की एक लंबी chain बन जाती है।

उदाहरण: Why Use Builder Pattern?

java
public class Main {
	static class Pizza {
		String size; boolean cheese;
		Pizza(String size, boolean cheese) { this.size = size; this.cheese = cheese; }
	}
	public static void main(String[] args) {
		// Avoids a telescoping constructor for every combination of optional toppings
		Pizza p = new Pizza("large", true);
		System.out.println(p.size + " " + p.cheese);
	}
}

Inner Static Builder Class

एक आम Java implementation एक static Builder class को उस class के अंदर nest करती है जिसे यह बनाती है। Builder chained setter-style calls के ज़रिए configuration values जमा करता है, और एक आखिरी build() method उन जमा की गई values का उपयोग असली outer-class instance बनाने और return करने के लिए करता है।

उदाहरण: Inner Static Builder Class

java
// Define the class Main
public class Main {
	// Define the class Pizza
	static class Pizza {
		String size; boolean cheese;
		private Pizza(Builder b) { this.size = b.size; this.cheese = b.cheese; }
		static class Builder {
			String size; boolean cheese;
			Builder size(String size) { this.size = size; return this; }
			Builder cheese(boolean cheese) { this.cheese = cheese; return this; }
			Pizza build() { return new Pizza(this); }
		}
	}
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		Pizza p = new Pizza.Builder().size("medium").cheese(true).build();
		// Print a line to the console
		System.out.println(p.size + " " + p.cheese);
	}
}

Handling Mandatory and Optional Fields

कुछ fields को mandatory बनाने के लिए, उन्हें सीधे Builder के अपने constructor में parameters के रूप में require करें ताकि उनके बिना कोई object न बन सके। इसके विपरीत, optional fields को बाद में अलग chainable methods के ज़रिए सेट किया जा सकता है जिन्हें caller छोड़ने के लिए स्वतंत्र है।

उदाहरण: Handling Mandatory and Optional Fields

java
public class Main {
	static class Order {
		final String item; String note;
		private Order(Builder b) { this.item = b.item; this.note = b.note; }
		static class Builder {
			final String item; // mandatory -- required by the Builder's own constructor
			String note; // optional
			Builder(String item) { this.item = item; }
			Builder note(String note) { this.note = note; return this; }
			Order build() { return new Order(this); }
		}
	}
	public static void main(String[] args) {
		Order o = new Order.Builder("Book").note("Gift wrap").build();
		System.out.println(o.item + " " + o.note);
	}
}

Thread Safety and Immutability

outer, built class पर setter methods को पूरी तरह छोड़कर, Builder जो objects produce करता है वे बनने के बाद immutable और inherently thread-safe रहते हैं। आप build() method के अंदर ही cross-field constraints के validation को केंद्रीकृत भी कर सकते हैं, object के अस्तित्व में आने से पहले ही invalid combinations पकड़ते हुए।

उदाहरण: Thread Safety and Immutability

java
public class Main {
	static final class Point {
		final int x, y; // no setters -- immutable once built
		private Point(Builder b) {
			if (b.x < 0 || b.y < 0) throw new IllegalArgumentException("negative coordinates");
			this.x = b.x; this.y = b.y;
		}
		static class Builder {
			int x, y;
			Builder x(int x) { this.x = x; return this; }
			Builder y(int y) { this.y = y; return this; }
			Point build() { return new Point(this); }
		}
	}
	public static void main(String[] args) {
		Point p = new Point.Builder().x(3).y(4).build();
		System.out.println(p.x + "," + p.y);
	}
}

Real-World Scenarios

Builders असली code में भारी उपयोग होते हैं बहुत सारे optional headers और parameters के साथ HTTP requests configure करने के लिए, जटिल SQL queries को टुकड़ों में बनाने के लिए, और application configuration objects assemble करने के लिए जिनमें दर्जनों स्वतंत्र रूप से optional settings हों।

उदाहरण: Real-World Scenarios

java
// Define the class Main
public class Main {
	// Define the class HttpRequestBuilder
	static class HttpRequestBuilder {
		String url; String method = "GET"; String header;
		HttpRequestBuilder url(String url) { this.url = url; return this; }
		HttpRequestBuilder method(String method) { this.method = method; return this; }
		HttpRequestBuilder header(String header) { this.header = header; return this; }
		String build() { return method + " " + url + " [" + header + "]"; }
	}
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Create a new HttpRequestBuilder object and store it in request
		String request = new HttpRequestBuilder().url("/api/users").method("POST").header("Auth").build();
		// Print a line to the console
		System.out.println(request);
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. builder methods को this के बजाय void return करवाना, जो chained calls को तोड़ देता है।
  2. build() में mandatory fields को validate न करना, जिससे एक अधूरा object बन जाता है।
  3. built class में setters जोड़ना, जो वह immutability हटा देता है जो Builder को देनी थी।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.