क्या ऑब्जेक्ट इनिशियललाइज़र के साथ बिल्डरों और फ्लुइड इंटरफेस का उपयोग करने का कोई मतलब है?


10

जावा और सी # में, आप उन गुणों के साथ एक ऑब्जेक्ट बना सकते हैं जो किसी निर्माणकर्ता को मापदंडों के साथ परिभाषित करके, ऑब्जेक्ट के निर्माण के बाद प्रत्येक संपत्ति को परिभाषित करके या बिल्डर / तरल पदार्थ इंटरफ़ेस पैटर्न का उपयोग करके निर्धारित किया जा सकता है। हालाँकि, C # 3 ने ऑब्जेक्ट और कलेक्शन इनिशियलाइज़र्स को पेश किया, जिसका मतलब था कि बिल्डर पैटर्न काफी हद तक बेकार था। बिना इनिशियलाइज़र्स वाली भाषा में, कोई बिल्डर लागू कर सकता है, फिर उसका उपयोग इस तरह से कर सकता है:

Vehicle v = new Vehicle.Builder()
                    .manufacturer("Toyota")
                    .model("Camry")
                    .year(1997)
                    .colour(CarColours.Red)
                    .addSpecialFeature(new Feature.CDPlayer())
                    .addSpecialFeature(new Feature.SeatWarmer(4))
                    .build();

इसके विपरीत, C # में एक लिख सकता है:

var vehicle = new Vehicle {
                Manufacturer = "Toyota",
                Model = "Camry",
                Year = 1997,
                Colour = CarColours.Red,
                SpecialFeatures = new List<SpecialFeature> {
                    new Feature.CDPlayer(),
                    new Feature.SeatWarmer { Seats = 4 }
                }
              }

... एक बिल्डर की आवश्यकता को समाप्त करना जैसा कि पिछले उदाहरण में देखा गया है।

इन उदाहरणों के आधार पर, क्या बिल्डर अभी भी C # में उपयोगी हैं, या वे पूरी तरह से इनिशियलाइज़र द्वारा अधिगृहीत किए गए हैं?


are builders usefulमैं इस प्रकार के प्रश्नों को क्यों देखता रहूं? एक बिल्डर एक डिज़ाइन पैटर्न है - निश्चित रूप से, इसे एक भाषा सुविधा के रूप में उजागर किया जा सकता है लेकिन दिन के अंत में यह सिर्फ एक डिज़ाइन पैटर्न है। एक डिज़ाइन पैटर्न "गलत" नहीं हो सकता। यह आपके उपयोग के मामले को पूरा कर सकता है या नहीं भी कर सकता है, लेकिन यह पूरे पैटर्न को गलत नहीं बनाता है, बस इसका अनुप्रयोग। याद रखें कि दिन के अंत में डिज़ाइन पैटर्न विशेष समस्याओं को हल करते हैं - यदि आप समस्या का सामना नहीं करते हैं, तो आप इसे हल करने का प्रयास क्यों करेंगे?
व्लाज

@vlaz मैं यह नहीं कह रहा हूं कि बिल्डर गलत हैं - वास्तव में मेरा सवाल यह पूछ रहा था कि क्या बिल्डरों के लिए कोई उपयोग के मामले दिए गए हैं जो शुरुआती लोगों द्वारा दिए गए सबसे आम मामले का एक कार्यान्वयन है जहां आप बिल्डरों का उपयोग करेंगे। जाहिर है, लोगों ने जवाब दिया है कि एक बिल्डर अभी भी निजी क्षेत्रों की स्थापना के लिए उपयोगी है, जिसने बदले में मेरे सवाल का जवाब दिया है।
svbnet

3
@vlaz स्पष्ट करने के लिए: मैं कह रहा हूँ कि इनिशियलाइज़र्स ने बड़े पैमाने पर "पारंपरिक" बिल्डर / द्रव इंटरफ़ेस के पैटर्न को एक आंतरिक बिल्डर वर्ग को लिखने के लिए बदल दिया है, फिर उस वर्ग के अंदर चाइनिंग सेटर विधियों को लिखना जो उस मूल वर्ग का एक नया उदाहरण बनाते हैं। मैं यह नहीं कह रहा हूं कि शुरुआती लोग उस विशिष्ट बिल्डर पैटर्न के लिए एक प्रतिस्थापन हैं; मैं कह रहा हूं कि इनिशियलाइजर्स डेवलपर्स को उस विशिष्ट बिल्डर पैटर्न को लागू करने के लिए बचाते हैं , जवाब में वर्णित उपयोग के मामलों के लिए बचाते हैं , जो बिल्डर पैटर्न को बेकार नहीं बनाता है।
svnetnet

5
@vlaz मैं आपकी चिंता नहीं समझता। "आप कह रहे थे कि एक डिज़ाइन पैटर्न उपयोगी नहीं है" - नहीं, जो पूछ रहा था कि क्या एक डिज़ाइन पैटर्न उपयोगी है। वह गलत, गलत या गलत प्रश्न कैसे है? क्या आपको लगता है कि उत्तर स्पष्ट है? मुझे नहीं लगता कि उत्तर स्पष्ट है; यह मुझे एक अच्छा सवाल लगता है।
टान्नर स्वेट

2
@vlaz, सिंगलटन और सर्विस लोकेटर पैटर्न गलत हैं। एर्गो डिजाइन पैटर्न गलत हो सकते हैं।
डेविड अर्नो

जवाबों:


12

जैसा कि @ user248215 द्वारा छुआ गया है, वास्तविक मुद्दा अपरिवर्तनीयता है। सी # में एक बिल्डर का उपयोग करने का कारण यह होगा कि आप बिना किसी सेटलमेंट के एक्सप्लोसिव को बनाए रखने के लिए सेटलेबल प्रॉपर्टीज का खुलासा कर सकें। यह एनकैप्सुलेशन का सवाल नहीं है जिसके कारण मैंने अपना जवाब लिखा है। एनकैप्सुलेशन काफी ओर्थोगोनल है क्योंकि एक सेटर को लागू करने का मतलब यह नहीं है कि सेटर वास्तव में क्या करता है या आपको इसके कार्यान्वयन के लिए बाध्य करता है।

C #, 8.0 के अगले संस्करण में, एक ऐसे withकीवर्ड को पेश करने की संभावना है जो अपरिवर्तनीय वस्तुओं को स्पष्ट रूप से और संक्षिप्त रूप से बिल्डरों को लिखने की आवश्यकता के बिना आरंभ करने की अनुमति देगा।

एक और दिलचस्प बात आप बिल्डरों के साथ कर सकते हैं, जैसा कि शुरुआती के विपरीत है, यह है कि वे विभिन्न प्रकार के ऑब्जेक्ट्स में परिणाम कर सकते हैं जिन्हें कहा जाता है तरीकों के अनुक्रम के आधार पर।

उदाहरण के लिए

value.Match()
    .Case((DateTime d) => Console.WriteLine($"{d: yyyy-mm-dd}"))
    .Case((double d) => Console.WriteLine(Math.Round(d, 4));
    // void

var str = value.Match()
    .Case((DateTime d) => $"{d: yyyy-mm-dd}")
    .Case((double d) => Math.Round(d, 4).ToString())
    .ResultOrDefault(string.Empty);
    // string

ऊपर दिए गए उदाहरण को स्पष्ट करने के लिए, यह एक पैटर्न मिलान पुस्तकालय है जो मामलों को निर्दिष्ट करके "मैच" बनाने के लिए बिल्डर पैटर्न का उपयोग करता है। Caseइसे पास करने की विधि कहकर मामलों को जोड़ा जाता है। यदि valueफ़ंक्शन के पैरामीटर प्रकार के लिए यह असाइन किया गया है। आप गीथहब पर पूर्ण स्रोत कोड पा सकते हैं और, क्योंकि XML टिप्पणियों को सादे पाठ में पढ़ना मुश्किल है, यहां सैंडकास्टल निर्मित प्रलेखन ( रिमार्क्स अनुभाग देखें) की एक कड़ी है


मैं यह नहीं देखता कि एक IEnumerable<Func<T, TResult>>सदस्य का उपयोग करके यह कैसे एक वस्तु आरंभीकरण नहीं किया जा सकता है ।
केलथ

@ कैलेथ वास्तव में ऐसा कुछ था जिसका मैंने प्रयोग किया था लेकिन उस दृष्टिकोण के साथ कुछ मुद्दे हैं। यह सशर्त खंडों के लिए अनुमति नहीं देता (दिखाया नहीं गया है लेकिन लिंक किए गए दस्तावेज़ों में इसका उपयोग और प्रदर्शन किया गया है) और यह प्रकार के निष्कासन की अनुमति नहीं देता है TResult। अंतत: टाइप-इनफ्रेंस का इसके साथ बहुत कुछ था। मैं यह भी चाहता था कि एक नियंत्रण संरचना की तरह "देखो"। इसके अलावा, मैं एक शुरुआती का उपयोग नहीं करना चाहता था क्योंकि यह म्यूटेशन की अनुमति देगा।
अलुआन हद्दद

12

ऑब्जेक्ट इनिशियलाइज़र को आवश्यकता होती है कि कॉलिंग कोड द्वारा गुण सुलभ होना चाहिए। नेस्टेड बिल्डर्स वर्ग के निजी सदस्यों तक पहुंच सकते हैं।

यदि आप Vehicleअपरिवर्तनीय बनाना चाहते हैं (सभी निजी बसाने के माध्यम से), तो नेस्टेड बिल्डर का उपयोग निजी चर सेट करने के लिए किया जा सकता है।


0

वे सभी विभिन्न उद्देश्यों की सेवा करते हैं !!!

कंस्ट्रक्टर्स उन फ़ील्ड्स को इनिशियलाइज़ कर सकते हैं जो readonlyनिजी और संरक्षित सदस्यों के रूप में चिह्नित हैं । हालाँकि, आप कुछ हद तक सीमित कर सकते हैं कि आप एक कंस्ट्रक्टर के अंदर क्या कर सकते हैं; thisउदाहरण के लिए, आपको किसी भी बाहरी तरीके से गुजरने से बचना चाहिए , और आपको आभासी सदस्यों को कॉल करने से बचना चाहिए, क्योंकि वे एक व्युत्पन्न वर्ग के संदर्भ में निष्पादित कर सकते हैं जो अभी तक खुद का निर्माण नहीं किया है। इसके अलावा, कंस्ट्रक्टरों को चलाने की गारंटी दी जाती है (जब तक कि कॉलर कुछ बहुत ही असामान्य नहीं हो जाता है), इसलिए यदि आप कंस्ट्रक्टर में फ़ील्ड सेट करते हैं, तो बाकी क्लास में कोड मान सकते हैं कि वे फ़ील्ड शून्य नहीं होने जा रहे हैं।

निर्माण के बाद शुरुआती भाग। वे केवल आपको सार्वजनिक संपत्ति कहते हैं; निजी और / या आसानी से फ़ील्ड सेट नहीं किए जा सकते हैं। अधिवेशन के द्वारा, एक संपत्ति की स्थापना का कार्य बहुत सीमित होना चाहिए, जैसे कि यह बेरोजगार होना चाहिए, और इसके सीमित दुष्प्रभाव हैं।

बिल्डर विधियाँ वास्तविक विधियाँ हैं और इसलिए एक से अधिक तर्क की अनुमति देती हैं, और अधिवेशन से वस्तु निर्माण सहित दुष्प्रभाव हो सकते हैं। जबकि वे आसानी से फ़ील्ड सेट नहीं कर सकते, वे बहुत कुछ और भी कर सकते हैं। इसके अलावा, तरीकों को विस्तार के तरीकों के रूप में लागू किया जा सकता है (जैसे कि LINQ कार्यक्षमता के बहुत सारे)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.