मैं धाराप्रवाह एपीआई को अपने द्वारा बनाए गए "बिल्डर" वर्ग से अलग कर दूंगा। इस तरह, यदि क्लाइंट धाराप्रवाह एपीआई का उपयोग नहीं करना चाहता है तो भी आप इसे मैन्युअल रूप से उपयोग कर सकते हैं और यह डोमेन ऑब्जेक्ट (एकल जिम्मेदारी सिद्धांत का पालन) को प्रदूषित नहीं करता है। इस मामले में निम्नलिखित बनाया जाएगा:
Car
जो डोमेन ऑब्जेक्ट है
CarBuilder
जो धाराप्रवाह एपीआई रखता है
उपयोग इस तरह होगा:
var car = CarBuilder.BuildCar()
.OfBrand(Brand.Ford)
.OfModel(12345)
.PaintedIn(Color.Silver)
.Build();
CarBuilder
वर्ग (मैं सी # नामकरण परंपरा यहाँ उपयोग कर रहा हूँ) इस प्रकार दिखाई देगा:
public class CarBuilder {
private Car _car;
/// Constructor
public CarBuilder() {
_car = new Car();
SetDefaults();
}
private void SetDefaults() {
this.OfBrand(Brand.Ford);
// you can continue the chaining for
// other default values
}
/// Starts an instance of the car builder to
/// build a new car with default values.
public static CarBuilder BuildCar() {
return new CarBuilder();
}
/// Sets the brand
public CarBuilder OfBrand(Brand brand) {
_car.SetBrand(brand);
return this;
}
// continue with OfModel(...), PaintedIn(...), and so on...
// that returns "this" to allow method chaining
/// Returns the built car
public Car Build() {
return _car;
}
}
ध्यान दें कि यह वर्ग थ्रेड सुरक्षित नहीं होगा (प्रत्येक थ्रेड के लिए इसे स्वयं CarBuilder उदाहरण की आवश्यकता होगी)। यह भी ध्यान दें कि, भले ही धाराप्रवाह एक बहुत अच्छी अवधारणा है, यह संभवतः साधारण डोमेन ऑब्जेक्ट बनाने के उद्देश्य से ओवरकिल है।
यह सौदा अधिक उपयोगी है यदि आप कुछ अधिक सार के लिए एक एपीआई बना रहे हैं और अधिक जटिल सेट अप और निष्पादन है, यही कारण है कि यह यूनिट परीक्षण और डीआई फ्रेमवर्क में बहुत अच्छा काम करता है। आप विकिपीडिया धाराप्रवाह इंटरफ़ेस लेख के जावा अनुभाग के तहत दृढ़ता, तिथि से निपटने और नकली वस्तुओं के साथ कुछ अन्य उदाहरण देख सकते हैं ।
संपादित करें:
जैसा कि टिप्पणियों से नोट किया गया है; आप बिल्डर वर्ग को एक स्थिर आंतरिक वर्ग (कार के अंदर) बना सकते हैं और कार को अपरिवर्तनीय बनाया जा सकता है। कार को अपरिवर्तनीय बनाने का यह उदाहरण थोड़ा मूर्खतापूर्ण लगता है; लेकिन एक अधिक जटिल प्रणाली में, जहां आप बिल्कुल उस वस्तु की सामग्री को बदलना नहीं चाहते हैं जो निर्मित है, आप इसे करना चाहते हैं।
नीचे एक उदाहरण दिया गया है कि दोनों स्थिर आंतरिक वर्ग कैसे करें और इसे बनाने वाली अपरिवर्तनीय वस्तु निर्माण को कैसे संभालें:
// the class that represents the immutable object
public class ImmutableWriter {
// immutable variables
private int _times; private string _write;
// the "complex" constructor
public ImmutableWriter(int times, string write) {
_times = times;
_write = write;
}
public void Perform() {
for (int i = 0; i < _times; i++) Console.Write(_write + " ");
}
// static inner builder of the immutable object
protected static class ImmutableWriterBuilder {
// the variables needed to construct the immutable object
private int _ii = 0; private string _is = String.Empty;
public void Times(int i) { _ii = i; }
public void Write(string s) { _is = s; }
// The stuff is all built here
public ImmutableWriter Build() {
return new ImmutableWriter(_ii, _is);
}
}
// factory method to get the builder
public static ImmutableWriterBuilder GetBuilder() {
return new ImmutableWriterBuilder();
}
}
उपयोग निम्नलिखित होगा:
var writer = ImmutableWriter
.GetBuilder()
.Write("peanut butter jelly time")
.Times(2)
.Build();
writer.Perform();
// console writes: peanut butter jelly time peanut butter jelly time
संपादित करें 2: टिप्पणियों में पीट ने जटिल डोमेन ऑब्जेक्ट्स के साथ यूनिट परीक्षण लिखने के संदर्भ में लंबर फ़ंक्शन के साथ बिल्डरों का उपयोग करने के बारे में एक ब्लॉग पोस्ट किया । यह बिल्डर को थोड़ा अधिक अभिव्यंजक बनाने के लिए एक दिलचस्प विकल्प है।
इसके CarBuilder
बजाय आपको इस विधि की आवश्यकता है:
public static Car Build(Action<CarBuilder> buildAction = null) {
var carBuilder = new CarBuilder();
if (buildAction != null) buildAction(carBuilder);
return carBuilder._car;
}
जिसका उपयोग इस प्रकार किया जा सकता है:
Car c = CarBuilder
.Build(car =>
car.OfBrand(Brand.Ford)
.OfModel(12345)
.PaintedIn(Color.Silver);
var car = new Car(Brand.Ford, 12345, Color.Silver);
?