डिपेंडेंसी इंजेक्शन और सर्विस लोकेटर पैटर्न के बीच अंतर क्या है?


304

दोनों पैटर्न नियंत्रण के व्युत्क्रम के सिद्धांत के कार्यान्वयन की तरह लगते हैं। यही है, कि एक वस्तु को यह नहीं पता होना चाहिए कि इसकी निर्भरता का निर्माण कैसे किया जाए।

निर्भरता इंजेक्शन (DI) एक निर्माता या सेटर का उपयोग करने के लिए लगता है कि यह "निर्भरता" है।

कंस्ट्रक्टर इंजेक्शन का उपयोग करने का उदाहरण:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

सेवा लोकेटर एक "कंटेनर" का उपयोग करता है, जो इसकी निर्भरता को बढ़ाता है और फू इट्स बार देता है।

सेवा लोकेटर का उपयोग करने का उदाहरण:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo()
  {
    this.bar = Container.Get<IBar>();
  }

  //...
}

क्योंकि हमारी निर्भरताएं केवल वस्तुएं हैं, इन निर्भरताओं में निर्भरताएं हैं, जिनकी और भी अधिक निर्भरताएं हैं, और इसी तरह आगे भी। इस प्रकार, कंट्रोल कंटेनर (या DI कंटेनर) का उलटा पैदा हुआ था। उदाहरण: कैसल विंडसर, निनजेक्ट, स्ट्रक्चर मैप, स्प्रिंग, आदि)

लेकिन एक IOC / DI कंटेनर बिल्कुल सर्विस लोकेटर की तरह दिखता है । क्या इसे डीआई कंटेनर एक बुरा नाम कह रहा है? क्या IOC / DI कंटेनर सिर्फ दूसरे प्रकार का सर्विस लोकेटर है? क्या इस तथ्य में अति सूक्ष्म अंतर है कि हम डीआई कंटेनरों का उपयोग तब करते हैं जब हमारे पास कई निर्भरताएं होती हैं?


13
नियंत्रण के उलट होने का मतलब है कि "किसी वस्तु को यह नहीं पता होना चाहिए कि उसकी निर्भरता का निर्माण कैसे किया जाए?"? वह मेरे लिए नया है। नहीं, वास्तव में, यह "नियंत्रण के व्युत्क्रम" का मतलब नहीं है। देखें martinfowler.com/bliki/InversionOfControl.html यह लेख यहां तक ​​कि शब्द की व्युत्पत्ति के लिए संदर्भ प्रदान करता है, जो 1980 के दशक में वापस आया था।
रोजेरियो

1
यहाँ जवाब दें: infoq.com/articles/Succeeding-D dependency
मार्क

1
मार्क सीमैन सेवा लोकेटर को विरोधी-प्रतिमान के रूप में तर्क देते हैं ( blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern )। इसके अलावा, मुझे आरेख मिला (यहां पाया गया, stackoverflow.com/a/9503612/1977871 ) DI और SL को समझने के लिए सहायक। उम्मीद है की यह मदद करेगा।
विवेकदेव

जवाबों:


181

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


20
इसके अतिरिक्त, आप कक्षा का निर्माण करते समय दोनों का उपयोग कर सकते हैं। डिफ़ॉल्ट निर्माणकर्ता निर्भरता प्राप्त करने के लिए SL का उपयोग कर सकता है, और उन्हें "वास्तविक" कंस्ट्रक्टर के पास भेज सकता है जो उन निर्भरता को प्राप्त करता है। आप दोनों दुनिया के सर्वश्रेष्ठ मिल गया है।
पालिन

6
नहीं, ServiceLocator किसी दिए गए निर्भरता (प्लगइन) के लिए सही कार्यान्वयन को तत्काल करने के लिए जिम्मेदार है। DI के मामले में, DI "कंटेनर" इसके लिए जिम्मेदार है।
रोजरियो

5
@Rogerio हाँ, लेकिन वर्ग को अभी भी सेवा लोकेटर के बारे में जानना है ... दो अवसाद हैं। विशेष रूप से क्षणिक वस्तुओं की सेवा के लिए विशेष रूप से क्षणिक वस्तुओं की तलाश के लिए मैंने डीआई कंटेनर में सेवा लोकेटर प्रतिनिधि को नहीं देखा है।
एडम गेंट

2
@ अदम ने यह नहीं कहा कि सेवा लोकेटर एक डीआई कंटेनर को सौंप देगा। ये दो परस्पर अनन्य पैटर्न हैं, जैसा कि "आधिकारिक" लेख में वर्णित है । मेरे लिए, सेवा लोकेटर का व्यवहार में DI पर बहुत बड़ा लाभ है: DI कंटेनर का उपयोग दुर्व्यवहार को आमंत्रित करता है (जिसे मैंने बार-बार देखा है), जबकि सेवा लोकेटर का उपयोग नहीं करता है।
रोजेरियो

3
"इसका एक महत्वपूर्ण परिणाम यह है कि DI उदाहरण इकाई परीक्षण के लिए बहुत आसान है - क्योंकि आप इसे अपनी मूल वस्तुओं के नकली कार्यान्वयन से पारित कर सकते हैं।" सच नहीं। आपकी इकाई परीक्षणों में, सेवा लोकेटर कंटेनर में एक रजिस्टर फ़ंक्शन के लिए कॉल का उपयोग आसानी से रजिस्ट्री में मक्स को जोड़ने के लिए किया जा सकता है।
ड्रमबेग

93

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

एक अच्छी तुलना: http://martinfowler.com/articles/injection.html

यदि आपका निर्भरता इंजेक्टर एक सेवा लोकेटर की तरह दिखता है, जहां कक्षाएं सीधे इंजेक्टर को बुलाती हैं, तो यह शायद एक निर्भरता इंजेक्टर नहीं है, बल्कि सेवा लोकेटर है।


17
लेकिन आप उस मामले को कैसे संभालते हैं जहां आपको रनटाइम के दौरान ऑब्जेक्ट बनाने होते हैं? यदि आप उन्हें "नए" के साथ मैन्युअल रूप से बनाते हैं तो आप DI का उपयोग नहीं कर सकते। यदि आप मदद के लिए DI फ्रेमवर्क कहते हैं, तो आप पैटर्न को तोड़ रहे हैं। तो क्या विकल्प बचे हैं?
बोरिस

9
@ बोरिस के समान समस्या थी और मैंने वर्ग विशेष के कारखानों को इंजेक्ट करने का निर्णय लिया। सुंदर नहीं है, लेकिन काम मिल गया। एक सुंदर समाधान देखना पसंद करेंगे।
चार्ली रुडेनस्टाल

तुलना करने के लिए सीधा लिंक: martinfowler.com/articles/…
Teoman shipahi

2
@ बोरिस अगर मुझे मक्खी पर नई वस्तुओं के निर्माण की आवश्यकता है तो मैंने कहा कि वस्तुओं के लिए एक सार फैक्टरी को इंजेक्ट किया जाएगा। जो इस उदाहरण में सेवा लोकेटर को इंजेक्ट करने के समान होगा, लेकिन संबंधित वस्तुओं के निर्माण के लिए एक ठोस, समान, संकलन-समय, इंटरफ़ेस प्रदान करता है और निर्भरता को स्पष्ट करता है।
LivePastTheEnd

51

सेवा लोकेटर निर्भरताएँ छिपाते हैं - आप किसी ऑब्जेक्ट को देखकर यह नहीं बता सकते हैं कि वह किसी डेटाबेस से टकराता है या नहीं (उदाहरण के लिए) जब वह किसी लोकेटर से कनेक्शन प्राप्त करता है। निर्भरता इंजेक्शन (कम से कम कंस्ट्रक्टर इंजेक्शन) के साथ निर्भरताएं स्पष्ट हैं।

इसके अलावा, सर्विस लोकेटर इनकैप्सुलेशन को तोड़ते हैं क्योंकि वे अन्य वस्तुओं की निर्भरता के लिए वैश्विक बिंदु प्रदान करते हैं। किसी भी सिंगलटन के साथ सेवा लोकेटर के साथ :

क्लाइंट ऑब्जेक्ट के इंटरफ़ेस के लिए पूर्व और पोस्ट की शर्तों को निर्दिष्ट करना मुश्किल हो जाता है, क्योंकि इसके कार्यान्वयन के कामकाज को बाहर से ध्यान दिया जा सकता है।

निर्भरता इंजेक्शन के साथ, एक बार एक वस्तु की निर्भरता निर्दिष्ट होने के बाद, वे स्वयं वस्तु के नियंत्रण में हैं।


3
मुझे पसंद है "सिंगलटन कंसीडेंट
चार्ल्स ग्राहम

2
मुझे ol 'स्टीव येजेज से प्यार है और उस लेख का शीर्षक बहुत अच्छा है, लेकिन मुझे लगता है कि मैंने जिस लेख का हवाला दिया था और मिचको हेवरी के "सिंगलेट्स पैथोलॉजिकल लियर्स हैं " ( misko.hevery.com/2008/08/17/singleons-are-pathological- झूठे ) सेवा लोकेटर के विशेष शैतान के खिलाफ एक बेहतर मामला बनाते हैं।
जेफ सनातन

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

1
With dependency injection (at least constructor injection) the dependencies are explicit.। कृपया समझाएँ।
FindOutIslamNow

ऊपर के रूप में, मैं नहीं देख सकता कि कैसे SL DI की तुलना में निर्भरता कम स्पष्ट करता है ...
माइकल पॉल्कोका

38

मार्टिन फाउलर कहते हैं :

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

संक्षेप में: सेवा लोकेटर और निर्भरता इंजेक्शन सिर्फ डिपेंडेंसी इनवर्जन सिद्धांत के कार्यान्वयन हैं।

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

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

आप इस पोस्ट की जाँच कर सकते हैं: डिपेंडेंसी इनवर्सन: सर्विस लोकेटर या डिपेंडेंसी इंजेक्शन

इसके अलावा क्लासिक: कंट्रोल कंटेनरों का विलोम और मार्टिन फाउलर द्वारा डिपेंडेंसी इंजेक्शन पैटर्न

राल्फ ई। जॉनसन और ब्रायन Foote द्वारा पुन: प्रयोज्य कक्षाएं डिजाइन करना

हालाँकि, जिसने मेरी आँखें खोली वह थीं: ASP.NET MVC: रिज़ॉल्यूशन या इंजेक्शन? यह मुद्दा है ... डिनो एस्पोसिटो द्वारा


शानदार सारांश: "सेवा लोकेटर और निर्भरता इंजेक्शन सिर्फ डिपेंडेंसी इनवर्जन सिद्धांत के कार्यान्वयन हैं।"
हंस

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

1
ServiceLocator और DI का "निर्भरता उलटा सिद्धांत" (DIP) से कोई लेना-देना नहीं है। डीआईपी उच्च स्तर के घटक को अधिक पुन: प्रयोज्य बनाने का एक तरीका है, उच्च-स्तरीय घटक के साथ परिभाषित एक सार प्रकार पर निर्भरता के साथ एक निम्न-स्तरीय घटक पर एक संकलन-समय की निर्भरता को प्रतिस्थापित करके, जो निम्न स्तर पर लागू होता है। स्तर घटक; इस तरह, संकलन-समय निर्भरता उलट हो जाती है, क्योंकि अब यह निम्न-स्तर का है जो उच्च-स्तर पर निर्भर करता है। इसके अलावा, ध्यान दें कि मार्टिन फाउलर का लेख बताता है कि DI और IoC एक ही चीज नहीं हैं ।
रोजेरियो

23

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

DI और SL एक साथ काम कर सकते हैं, हालाँकि। सामान्य निर्भरता (जैसे सेटिंग्स, लकड़हारा, आदि) के लिए एक केंद्रीय स्थान होना उपयोगी है। ऐसे डिपो का उपयोग करने वाले वर्ग को देखते हुए, आप एक "वास्तविक" कंस्ट्रक्टर बना सकते हैं जो डिप्स प्राप्त करता है, और एक डिफ़ॉल्ट (कोई पैरामीटर नहीं) कंस्ट्रक्टर जो एसएल से प्राप्त होता है और "असली" कंस्ट्रक्टर के लिए आगे आता है।

संपादित करें: और निश्चित रूप से, जब आप एसएल का उपयोग करते हैं, तो आप उस घटक को कुछ युग्मन पेश कर रहे हैं। जो विडंबना है, क्योंकि इस तरह की कार्यक्षमता का विचार गर्भपात को प्रोत्साहित करना और युग्मन को कम करना है। चिंताओं को संतुलित किया जा सकता है, और यह इस बात पर निर्भर करता है कि आपको SL का उपयोग करने के लिए कितने स्थानों की आवश्यकता होगी। जैसा कि ऊपर सुझाया गया है, बस डिफ़ॉल्ट क्लास कंस्ट्रक्टर में।


दिलचस्प! मैं दोनों DI और SL का उपयोग कर रहा हूं, लेकिन दो कंस्ट्रक्टर के साथ नहीं। तीन या चार सबसे उबाऊ अक्सर निर्भरता (सेटिंग्स, आदि ...) की जरूरत है मक्खी पर SL से प्राप्त करें। बाकी सब कुछ कंस्ट्रक्टर-इन-इंजेक्ट हो जाता है। यह थोड़ा बदसूरत है, लेकिन व्यावहारिक है।
मौर्टिनस

10

ये दोनों आईओसी की कार्यान्वयन तकनीकें हैं। अन्य पैटर्न भी हैं जो नियंत्रण के व्युत्क्रम को लागू करते हैं:

  • फैक्टरी पैटर्न
  • सेवा लोकेटर
  • डि (IoC) कंटेनर
  • निर्भरता इंजेक्शन (निर्माता इंजेक्शन, पैरामीटर इंजेक्शन (यदि आवश्यक नहीं है), इंटरफ़ेस इंजेक्शन के सेटर इंजेक्शन) ...

सेवा लोकेटर और DI कंटेनर अधिक समान लगते हैं, दोनों निर्भरता को परिभाषित करने के लिए एक कंटेनर का उपयोग करते हैं, जो कंक्रीट के कार्यान्वयन के लिए अमूर्तता को दर्शाता है।

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


7

अपने पिछले प्रोजेक्ट में मैं दोनों का उपयोग करता हूं। मैं यूनिट परीक्षण के लिए निर्भरता इंजेक्शन का उपयोग करता हूं। मैं कार्यान्वयन को छिपाने और अपने IoC कंटेनर पर निर्भर होने के लिए सेवा लोकेटर का उपयोग करता हूं। और हाँ! एक बार जब आप आईओसी कंटेनर (यूनिटी, निनजेक्ट, विंडसर कैसल) में से एक का उपयोग करते हैं तो आप उस पर निर्भर होते हैं। और एक बार जब यह पुराना हो जाता है या किसी कारण से अगर आप इसे स्वैप करना चाहते हैं, तो आपको कम से कम कंपोजिशन रूट - अपने कार्यान्वयन को बदलने की आवश्यकता होगी। लेकिन सेवा लोकेटर सार उस चरण।

आप अपने IoC कंटेनर पर निर्भर कैसे नहीं होंगे? या तो आपको इसे अपने आप से लपेटने की आवश्यकता होगी (जो एक बुरा विचार है) या आप सेवा लोकेटर का उपयोग अपने IoC कंटेनर को कॉन्फ़िगर करें। तो आप सेवा लोकेटर को बताएंगे कि आपको किस इंटरफ़ेस की आवश्यकता है, और यह उस इंटरफ़ेस को पुनः प्राप्त करने के लिए कॉन्फ़िगर किए गए IoC कंटेनर को कॉल करेगा।

मेरे मामले में, मैं ServiceLocator का उपयोग करता हूं जो एक फ्रेमवर्क घटक है। और IoC कंटेनर के लिए एकता का उपयोग करें । यदि भविष्य में मुझे अपने IoC कंटेनर को स्वैप करने की आवश्यकता है, तो मुझे केवल उन सभी चीजों की आवश्यकता होगी जो मुझे एकता के बजाय Ninject का उपयोग करने के लिए अपने सेवा लोकेटर को कॉन्फ़िगर करने की आवश्यकता है। आसान प्रवास।

यहाँ एक महान लेख इस परिदृश्य की व्याख्या करता है; http://www.johandekoning.nl/index.php/2013/03/03/dont-wrap-your-ioc-container/


Johandekoning लेख लिंक टूट गया है।
जेकज

6

मुझे लगता है कि दोनों एक साथ काम करते हैं।

निर्भरता इंजेक्शन का मतलब है कि आप कुछ आश्रित वर्ग / इंटरफ़ेस में उपभोग करने वाले वर्ग (आमतौर पर इसका निर्माण करने वाले) के लिए धक्का देते हैं। यह एक इंटरफेस के माध्यम से दो वर्गों को डिकॉय करता है और इसका मतलब है कि उपभोग करने वाला वर्ग कई प्रकार के "इंजेक्टेड निर्भरता" कार्यान्वयन के साथ काम कर सकता है।

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


6

जोड़ने का एक कारण, पिछले सप्ताह एमईएफ परियोजना के लिए लिखे गए एक प्रलेखन अद्यतन से प्रेरित होकर (मैं एमईएफ बनाने में मदद करता हूं)।

एक बार जब कोई एप्लिकेशन संभावित रूप से हजारों घटकों से बना होता है, तो यह निर्धारित करना मुश्किल हो सकता है कि क्या किसी विशेष घटक को सही ढंग से तत्काल बनाया जा सकता है। "त्वरित रूप से सही ढंग से" से, मेरा मतलब है कि Fooघटक के आधार पर इस उदाहरण में , का एक उदाहरण IBarऔर उपलब्ध होगा, और यह कि यह प्रदान करने वाला घटक होगा:

  • इसकी आवश्यक निर्भरताएं हैं,
  • किसी भी अवैध निर्भरता चक्र में शामिल नहीं है, और
  • MEF के मामले में, केवल एक उदाहरण के साथ आपूर्ति की जाए।

दूसरे उदाहरण आपके द्वारा दिया गया है, जहां निर्माता आईओसी कंटेनर को जाता है अपनी निर्भरता को पुनः प्राप्त करने के लिए, एक ही रास्ता है कि आप परीक्षण कर सकते हैं कि का एक उदाहरण Fooसही ढंग से instantiated जा करने के लिए सक्षम हो जाएगा अपने अनुप्रयोग की वास्तविक क्रम विन्यास के साथ करने के लिए है वास्तव में निर्माण यह

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

इस समस्या की जड़ में पहले से ही @Jon द्वारा कहा गया अंतर है: कंस्ट्रक्टर के माध्यम से निर्भरता को इंजेक्ट करना घोषणात्मक है, जबकि दूसरा संस्करण अनिवार्य सेवा लोकेटर पैटर्न का उपयोग करता है।

एक आईओसी कंटेनर, जब सावधानी से उपयोग किया जाता है, तो वास्तव में शामिल किए गए घटकों के किसी भी उदाहरण को बनाए बिना आपके ऐप के रनटाइम कॉन्फ़िगरेशन का विश्लेषण कर सकता है। कई लोकप्रिय कंटेनर इसमें से कुछ भिन्नता प्रदान करते हैं; Microsoft.Composition , जो MEF लक्ष्यीकरण का संस्करण है। .NET 4.5 वेब और मेट्रो शैली ऐप, CompositionAssertविकी प्रलेखन में एक नमूना प्रदान करता है । इसका उपयोग करके, आप कोड लिख सकते हैं जैसे:

 // Whatever you use at runtime to configure the container
var container = CreateContainer();

CompositionAssert.CanExportSingle<Foo>(container);

( इस उदाहरण को देखें )।

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

आशा है कि यह इस विषय पर उत्तर के व्यापक सेट के लिए एक दिलचस्प अतिरिक्त है!


5

नोट: मैं सवाल का बिल्कुल जवाब नहीं दे रहा हूं। लेकिन मुझे लगता है कि यह डिपेंडेंसी इंजेक्शन पैटर्न के नए शिक्षार्थियों के लिए उपयोगी हो सकता है जो सेवा लोकेटर (विरोधी) पैटर्न के साथ भ्रमित होते हैं जो इस पृष्ठ पर ठोकर खाते हैं।

मुझे सेवा लोकेटर के बीच का अंतर पता है (इसे अब एक एंटी-पैटर्न माना जाता है) और डिपेंडेंसी इंजेक्शन पैटर्न और प्रत्येक पैटर्न को ठोस उदाहरण समझ सकते हैं, फिर भी मैं कंस्ट्रक्टर के अंदर एक सेवा लोकेटर दिखा उदाहरणों द्वारा भ्रमित किया गया था (हम मान लें) पुनः निर्माता इंजेक्शन कर रहा है)।

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

ध्यान देने वाली बात यह है कि आप किसी DI लोकेटर के अंदर सर्विस लोकेटर ऑब्जेक्ट का उपयोग कर रहे होंगे, लेकिन आप "सर्विस लोकेटर पैटर्न" का उपयोग नहीं कर रहे हैं। यह कम भ्रामक है अगर कोई इसके बजाय एक आईओसी कंटेनर ऑब्जेक्ट के रूप में संदर्भित करता है, जैसा कि आपने अनुमान लगाया होगा कि वे अनिवार्य रूप से एक ही काम करते हैं (मुझे गलत होने पर सही करें)।

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

IMHO, इसे 'स्थान' या 'पता लगाने' के बजाय 'लोकेटर' का नाम दे रहा है, यह भी कभी-कभी एक कारण हो सकता है कि एक लेख में सेवा लोकेटर सेवा लोकेटर कंटेनर का उल्लेख कर रहा है, न कि सेवा लोकेटर (विरोधी) , खासकर जब एक संबंधित पैटर्न है जिसे डिपेंडेंसी इंजेक्शन कहा जाता है और डिपेंडेंसी इंजेक्टर नहीं।


4

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


4
हम्म मैं असहमत हूँ: सेवा लोकेटर पूर्व। स्पष्ट रूप से पता चलता है कि वहाँ अभी भी एक निर्भरता है ... सेवा लोकेटर। यदि barकक्षा में स्वयं पर निर्भरता है, तो barसेवा लोकेटर भी होगा, यह DI / IoC का उपयोग करने का पूरा बिंदु है।
GFoley83

2

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

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


1

सरल गर्भाधान के बाद मुझे सेवा लोकेटर और डि कंटेनर के बीच अंतर की स्पष्ट समझ मिली:

  • सेवा लोकेटर का उपयोग उपभोक्ता में किया जाता है और यह प्रत्यक्ष उपभोक्ता के अनुरोध पर कुछ भंडारण से आईडी द्वारा सेवाओं को खींचता है

  • DI कंटेनर कहीं बाहर स्थित है और यह कुछ भंडारण से सेवाएं लेता है और उन्हें उपभोक्ता को धकेलता है (कोई फर्क नहीं पड़ता निर्माता या विधि के माध्यम से)

हालाँकि, हम केवल ठोस उपभोक्ता उपयोग के संदर्भ में इनके बीच अंतर के बारे में बात कर सकते हैं। जब सेवा लोकेटर और डि कंटेनर का उपयोग रचना रूट में किया जाता है, तो वे लगभग समान होते हैं।


0

DI कंटेनर सर्विस लोकेटर का सुपरसेट है। यह एक सेवा का पता लगाने के लिए इस्तेमाल किया जा सकता है , निर्भरता के इंजेक्शन कोडांतरण (वायरिंग) की अतिरिक्त क्षमता के साथ ।


-2

रिकार्ड के लिए

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

जब तक आपको वास्तव में एक इंटरफ़ेस की आवश्यकता होती है (इंटरफ़ेस का उपयोग एक से अधिक वर्ग द्वारा किया जाता है), तो आपको इसका उपयोग नहीं करना चाहिए । इस मामले में, आईबीएआर किसी भी सेवा वर्ग का उपयोग करने की अनुमति देता है, जो इसे लागू करता है। हालांकि, आमतौर पर, इस इंटरफ़ेस का उपयोग एकल वर्ग द्वारा किया जाएगा।

क्यों एक इंटरफेस का उपयोग करने के लिए एक बुरा विचार है ?. क्योंकि डिबग करना वास्तव में कठिन है।

उदाहरण के लिए, मान लें कि उदाहरण "बार" विफल रहा, प्रश्न: कौन सा वर्ग विफल रहा ?। मुझे कौन सा कोड ठीक करना चाहिए? एक साधारण दृश्य, यह एक इंटरफ़ेस की ओर जाता है, और यह यहां है जहां मेरी सड़क समाप्त होती है।

इसके बजाय, यदि कोड एक कठिन निर्भरता का उपयोग करता है तो एक गलती को डीबग करना आसान है।

//Foo Needs an IBar
public class Foo
{
  private BarService bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

यदि "बार" विफल हो जाता है, तो मुझे क्लास बारसर्विस की जांच और फायर करना चाहिए।


1
एक वर्ग विशिष्ट वस्तु के निर्माण का एक खाका है। दूसरी ओर एक इंटरफ़ेस एक है contractऔर सिर्फ एक व्यवहार को परिभाषित करता है न कि कार्रवाई। वास्तविक ऑब्जेक्ट के आसपास से गुजरने के बजाय, केवल इंटरफ़ेस साझा किया जाता है ताकि उपभोक्ता आपकी शेष वस्तु तक न पहुंच सके। यूनिट परीक्षण के लिए भी यह केवल उस भाग का परीक्षण करने में मदद करता है जिसे परीक्षण करने की आवश्यकता है। मुझे लगता है कि समय में आप इसकी उपयोगिता को समझेंगे।
गुन्न
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.