इसका उद्देश्य डॉक ब्राउन के लिए एक पूरक उत्तर होना है, और साथ ही डीनाज़ की अनुत्तरित टिप्पणियों का जवाब देना है जो अभी भी प्रश्न से संबंधित हैं।
आपको शायद डीआई करने के लिए एक रूपरेखा की आवश्यकता है। जटिल पदानुक्रम होने का मतलब खराब डिजाइन नहीं है, लेकिन अगर आपको सीधे डी को इंजेक्ट करने के बजाय टाइमफैक्टिव बॉटम-अप (ए से डी) इंजेक्षन करना है तो शायद आप डिपेंडेंसी इंजेक्शन कर रहे हैं।
एक सिंगलटन? जी नहीं, धन्यवाद। यदि आपको केवल एक इस् टेंस की आवश्यकता है, तो इसे अपने आवेदन के संदर्भ में साझा करें (डिओ इंफ़ोरर ++ के लिए एक आईओसी कंटेनर का उपयोग करके, केवल टाइमफ़ेक्ट को एकल इस् टेंस के रूप में बाँधने की आवश्यकता है), यहाँ उदाहरण है (C ++ 11 वैसे, लेकिन C ++। C ++ 11 को पहले से ही (आपको मुफ्त में लीक से मुक्त आवेदन मिलता है):
Infector::Container ioc; //your app's context
ioc.bindSingleAsNothing<TimeFactory>(); //declare TimeFactory to be shared
ioc.wire<TimeFactory>(); //wire its constructor
// if you want to be sure TimeFactory is created at startup just request it
// (else it will be created lazily only when needed)
auto myTimeFactory = ioc.buildSingle<TimeFactory>();
अब आईओसी कंटेनर का अच्छा बिंदु यह है कि आपको डी तक टाइम फैक्ट्री पास करने की जरूरत नहीं है अगर आपकी क्लास को "डी" टाइम फैक्ट्री की जरूरत है, तो क्लास डी के लिए कंस्ट्रक्टर पैरामीटर के रूप में टाइम फैक्ट्री लगाएं।
ioc.bindAsNothing<A>(); //declare class A
ioc.bindAsNothing<B>(); //declare class B
ioc.bindAsNothing<D>(); //declare class D
//constructors setup
ioc.wire<D, TimeFactory>(); //time factory injected to class D
ioc.wire<B, D>(); //class D injected to class B
ioc.wire<A, B>(); //class B injected to class A
जैसा कि आप देखते हैं कि आप केवल एक बार TimeFactory इंजेक्षन करते हैं। "ए" का उपयोग कैसे करें? बहुत ही सरल, हर वर्ग को इंजेक्ट किया जाता है, मुख्य कारखाने में बनाया जाता है या कारखाने से अलग किया जाता है।
auto myA1 = ioc.build<A>(); //A is not "single" so many different istances
auto myA2 = ioc.build<A>(); //can live at same time
हर बार जब आप क्लास ए बनाते हैं तो यह स्वचालित रूप से (आलसी आइसटैंटेशन) होगा जो डी और डी तक निर्भरता के साथ इंजेक्ट किया जाएगा। टाइमफैक्ट के साथ इंजेक्ट किया जाएगा, इसलिए केवल 1 विधि को कॉल करके आप अपना पूरा पदानुक्रम तैयार है (और जटिल पदानुक्रम इस तरह से हल किए जाते हैं। बॉयलर प्लेट कोड का एक बहुत) को हटाना: आपको "नया / हटाएं" कॉल करने की आवश्यकता नहीं है और यह बहुत महत्वपूर्ण है क्योंकि आप एप्लिकेशन तर्क को गोंद कोड से अलग कर सकते हैं।
D, केवल D के पास हो सकने वाली सूचना के साथ समय ऑब्जेक्ट्स बना सकता है
यह आसान है, आपके TimeFactory में एक "create" विधि है, फिर बस एक अलग हस्ताक्षर "create (params)" का उपयोग करें और आप कर रहे हैं। पैरामीटर जो कोई निर्भरता नहीं हैं, अक्सर इस तरह से हल किए जाते हैं। यह "स्ट्रिंग्स" या "पूर्णांक" जैसी चीजों को इंजेक्ट करने के कर्तव्य को भी हटा देता है, क्योंकि यह केवल अतिरिक्त बॉयलर प्लेट को जोड़ता है।
कौन बनाता है कौन? आईओसी कंटेनर आइसटेंस और फैक्ट्रीज बनाता है, फैक्ट्रियां बाकियों का निर्माण करती हैं (फैक्ट्रियां मनमानी मापदंडों के साथ विभिन्न ऑब्जेक्ट्स बना सकती हैं, इसलिए आपको वास्तव में फैक्ट्रियों के लिए राज्य की आवश्यकता नहीं है)। आप अभी भी IoC कंटेनर के लिए रैपर के रूप में कारखानों का उपयोग कर सकते हैं: आम तौर पर बोलते हुए IoC कंटेनर बहुत खराब है और सेवा लोकेटर का उपयोग करने के समान है। कुछ लोगों ने IoC कंटेनर को एक कारखाने में लपेटकर समस्या का हल किया (यह कड़ाई से आवश्यक नहीं है, लेकिन यह लाभ है कि कंटेनर द्वारा पदानुक्रम हल किया गया है और आपके सभी कारखानों को बनाए रखना आसान हो जाता है)।
//factory method
std::unique_ptr<myType> create(params){
auto istance = ioc->build<myType>(); //this code's agnostic to "myType" hierarchy
istance->setParams(params); //the customization you needed
return std::move(istance);
}
निर्भरता इंजेक्शन का दुरुपयोग न करें, सरल प्रकार केवल कक्षा के सदस्य या स्थानीय स्कोप किए गए चर हो सकते हैं। यह स्पष्ट प्रतीत होता है, लेकिन मैंने देखा कि लोग "std :: वेक्टर" को सिर्फ इसलिए इंजेक्ट कर रहे थे क्योंकि एक DI फ्रेमवर्क था जो इसकी अनुमति देता था। हमेशा Demeter के नियम को याद रखें: "केवल वही इंजेक्ट करें जो आपको वास्तव में इंजेक्ट करने की आवश्यकता है"