2009-03-05 11 views
7

निर्भरता इंजेक्शन को लागू करने के तरीकों में से एक उद्देश्य व्यापार तर्क से वस्तु निर्माण को अलग करना है। आमतौर पर, इसमें ऑब्जेक्ट सृजन के लिए फैक्ट्री का उपयोग करना शामिल है।क्या फैक्टरी विधि में पैरामीटर पास करना ठीक है?

इस क्षण तक, मैं गंभीरता से एक फैक्टरी का उपयोग कर कभी नहीं माना जाता है तो मैं माफी माँगता हूँ इस सवाल का एक छोटा सा साधारण लगता है, तो:

फैक्टरी पैटर्न के सारे उदाहरण है कि मैं के पार चला गया है में, मैं हमेशा बहुत सरल उदाहरण देखें जिनमें पैरामीटर नहीं है। उदाहरण के लिए, यहां Misko Hevery's उत्कृष्ट How To Think About the "new" Operator आलेख से चोरी की गई फैक्टरी है।

 
class ApplicationBuilder { 
    House build() { 
    return new House(new Kitchen(
       new Sink(), 
       new Dishwasher(), 
       new Refrigerator()) 
      ); 
    } 
} 

हालांकि, अगर मैं प्रत्येक घर का नाम बनाने के लिए तैयार करता हूं तो क्या होता है? क्या मैं अभी भी फैक्टरी पैटर्न का उपयोग कर रहा हूं यदि मैं इस कोड को फिर से लिखूं?

 
class ApplicationBuilder { 
    House build(const std::string & house_name) { 
    return new House(house_name, 
         new Kitchen(new Sink(), 
            new Dishwasher(), 
            new Refrigerator()) 
        ); 
    } 
} 

ध्यान दें कि मेरी फैक्टरी विधि कॉल इस से बदल गया है:

 
ApplicationBuilder builder; 
House * my_house = builder.build();
इस के लिए

:

 
ApplicationBuilder builder; 
House * my_house = builder.build("Michaels-Treehouse");

वैसे: मैं वस्तु को अलग करने की अवधारणा व्यापार तर्क से instantiating लगता है अच्छा है, मैं बस यह पता लगाने की कोशिश कर रहा हूं कि मैं इसे अपनी स्थिति में कैसे लागू कर सकता हूं। मुझे क्या भ्रमित करता है कि फैक्टरी पैटर्न के बारे में मैंने जो भी उदाहरण देखा है, वे कभी भी बिल्ड() फ़ंक्शन में किसी भी पैरामीटर को पास नहीं करते हैं।

स्पष्ट होने के लिए: मुझे इसे तुरंत चालू करने से पहले पल तक घर का नाम नहीं पता।

+0

मैंने अक्सर देखा है कि कारखानों ने पैरामीटर लेते हैं जैसा आपने दिखाया है। इसमें कुछ भी गलत नहीं है। या आपके प्रश्न के संदर्भ में। यह बिल्कुल ठीक है। – grieve

उत्तर

8

मैंने बहुत सारे उदाहरण देखे हैं जो तर्कों के एक निश्चित सेट का उपयोग करते हैं, जैसे कि आपके नाम के उदाहरण में, और उन्हें स्वयं भी इस्तेमाल किया है और मैं इसके साथ कुछ भी गलत नहीं देख सकता।

हालांकि इसका कोई खास कारण है कि कई ट्यूटोरियल या छोटे लेख कारखानों कि आगे का निर्माण वस्तुओं के लिए मानकों को दिखाने से बचते है: यह व्यावहारिक रूप से तर्कों की मनमाना संख्या अग्रेषित करने के लिए (यहां तक ​​कि 6 तर्क की तरह एक समझदार सीमा के लिए) असंभव है। यदि आप इसे सामान्य करना चाहते हैं तो आपके द्वारा अग्रेषित प्रत्येक पैरामीटर को const T& और T& के रूप में स्वीकार किया जाना चाहिए।

अधिक जटिल उदाहरणों के लिए, हालांकि, आपको ओवरलोड (प्रत्येक पैरामीटर, एक कॉन्स और एक गैर-संस्करण संस्करण) के लिए तेजी से बढ़ते सेट की आवश्यकता है और perfect forwarding बिल्कुल संभव नहीं है (ताकि अस्थायी को अस्थायी के रूप में अग्रेषित किया जा सके, उदाहरण के लिए) । अगले सी ++ मानक के लिए कि इस मुद्दे को हल किया जाता है:

class ApplicationBuilder { 
    template<typename... T> 
    House *build(T&&... t) { 
    return new House(std::forward<T>(t)..., 
         new Kitchen(new Sink(), 
            new Dishwasher(), 
            new Refrigerator()) 
        ); 
    } 
}; 

इस तरह, आप

builder.build("Hello", 13); 

कॉल कर सकते हैं और यह वापस आ जाएगी

new House("Hello", 13, new Kitchen(new Sink(... 

लेख मैं ऊपर लिंक पढ़ें।

+0

रैवल्यू संदर्भों के बारे में अच्छा लिंक! यह शायद प्रश्न के दायरे से बाहर है, लेकिन यह इस विषय पर मैंने पढ़ा है कि सबसे स्पष्ट लेख है। –

5

मुझे नहीं पता कि यह पैरामीटर आपके कारखाने में क्यों जोड़ना गलत होगा। लेकिन ध्यान रखें कि आपको कई पैरामीटर जोड़ने को समाप्त नहीं करना चाहिए जो कारखाने द्वारा बनाई गई सभी वस्तुओं के लिए उपयोगी नहीं हो सकते हैं। यदि आप करते हैं, तो आप कारखाने के बहुत सारे फायदे खो देंगे!

+0

यह बताकर कि आप किस प्रकार की वस्तु चाहते हैं (पैराम्स में) यह फैक्ट्री को पूरी तरह से अलग-अलग ऑब्जेक्ट्स (बेस-क्लास या इंटरफ़ेस लौटकर) लौटा सकता है। – Aardvark

1

मैं बेनोइट से सहमत हूं। एसक्यूएल कनेक्शन जैसे कुछ बनाने के लिए कारखाने के बारे में सोचें, हालांकि इस तरह के मामले में कारखाने के कनेक्शन के बारे में जानकारी पास करना आवश्यक होगा। कारखाना सही सर्वर प्रोटोकॉल का उपयोग करने के लिए उस जानकारी का उपयोग करेगा और इसी तरह।

4

फैक्ट्री का विचार यह है कि यह आपको कक्षा/इंटरफ़ेस का उदाहरण देता है, इसलिए पास पैरामीटर के साथ कुछ भी गलत नहीं है। यदि वहां थे, तो पैरामीटर को एक नए() के साथ पास करना भी बुरा होगा।

5

न केवल स्वीकार्य है, लेकिन यह सामान्य फ़ैक्टरी विधि के पैरामीटर पास करने के लिए है। some examples देखें। आम तौर पर पैरामीटर एक प्रकार का कारखाना बताता है जो बनाना है, लेकिन कोई कारण नहीं है कि आप किसी ऑब्जेक्ट को बनाने के लिए आवश्यक अन्य जानकारी नहीं जोड़ सकते हैं। मुझे लगता है कि आप क्या कर रहे हैं ठीक है।

1

ज़रूर, क्यों नहीं ..!

पास पैरामीटर के बारे में अच्छी बात यह है कि यह आपको ठोस वस्तु के कार्यान्वयन को छिपाने की अनुमति देता है। उदाहरण के लिए, आपके द्वारा पोस्ट किए गए कोड में आप पैरामीटर को कन्स्ट्रक्टर को पास करते हैं। हालांकि, आप कार्यान्वयन को बदल सकते हैं ताकि वे इनिटियाइज़ विधि के माध्यम से पारित हो जाएं। फैक्ट्री विधि में पैरामीटर पास करके आप कॉलर से ऑब्जेक्ट बनाने और प्रारंभ करने की प्रकृति को छुपाते हैं।

1

लोकी :: फैक्ट्री पर एक नज़र डालें, हालांकि इसमें बूस्ट के साथ-साथ एक कार्यान्वयन भी बहुत कुछ है। मैं नियमित रूप से अलग प्रकार में उपलब्ध का उपयोग कुछ उदाहरण कोड:

लोकी typedef :: SingletonHolder < लोकी :: फैक्टरी < घटक, std :: स्ट्रिंग, लोकी :: Typelist < स्थिरांक DataCollection &, लोकी :: Typelist < खेल *, लोकी :: नलटाइप>>>> घटक फैक्ट्री;

यह पहली नजर में थोड़ा अजीब लग सकता है, हालांकि मुझे इस जानवर को समझाएं और यह वास्तव में कितना शक्तिशाली है। असल में हम एक सिंगलटन बनाते हैं जिसमें एक कारखाना होता है, अधिकांश पैरामीटर सिंगलटन के लिए होते हैं, घटक हमारे उत्पाद होते हैं, std :: स्ट्रिंग हमारी रचना आईडी प्रकार है, इसके बाद यह पैरामीटर की एक प्रकार की सूची का पालन करता है जो घटकों के निर्माण के लिए आवश्यक है (इसे एक मैक्रो के साथ-साथ कम वर्बोज सिंटैक्स के लिए भी परिभाषित किया जा सकता है)। इस लाइन के बाद कोई भी कर सकता है:

घटक फैक्टरी :: इंस्टेंस()। CreateObject ("someStringAssociatedWithConcreteType", anDataCollection, aGamePointer);

वस्तुओं को बनाने के लिए, केवल एक पंजीकृत करने के लिए घटक घटक :: इंस्टेंस()। रजिस्टर() ;. आधुनिक सी ++ डिजाइन पुस्तक में विवरण पर एक महान अध्याय है।

संबंधित मुद्दे