design patterns - निर्भरता इंजेक्शन क्या है?




design-patterns language-agnostic (20)

निर्भरता इंजेक्शन के बारे में विशिष्ट प्रश्नों के साथ पहले से ही कई प्रश्न पोस्ट किए गए हैं, जैसे कि इसका उपयोग कब करें और इसके लिए कौन से ढांचे हैं। हालाँकि,

निर्भरता इंजेक्शन क्या है और इसे कब / क्यों उपयोग किया जाना चाहिए या नहीं?


निर्भरता इंजेक्शन क्या है?

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

स्प्रिंग में निर्भरता इंजेक्शन कैसे काम करता है:

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

नियंत्रण में उलटा (आईओसी)

आईओसी एक सामान्य अवधारणा है और इसे कई अलग-अलग तरीकों से व्यक्त किया जा सकता है और निर्भरता इंजेक्शन आईओसी का एक ठोस उदाहरण है।

दो प्रकार की निर्भरता इंजेक्शन:

  1. कन्स्ट्रक्टर इंजेक्शन
  2. सेटर इंजेक्शन

1. कन्स्ट्रक्टर-आधारित निर्भरता इंजेक्शन:

कन्स्ट्रक्टर-आधारित डी को पूरा किया जाता है जब कंटेनर कई तर्कों के साथ एक वर्ग कन्स्ट्रक्टर को आमंत्रित करता है, प्रत्येक दूसरे वर्ग पर निर्भरता का प्रतिनिधित्व करता है।

public class Triangle {

private String type;

public String getType(){
    return type;
 }

public Triangle(String type){   //constructor injection
    this.type=type;
 }
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
        <constructor-arg value="20"/>
  </bean>

2. सेटर-आधारित निर्भरता इंजेक्शन:

सेटर-आधारित डी आपके बीन को तुरंत चालू करने के लिए नो-तर्क कन्स्ट्रक्टर या नो-तर्क स्थैतिक फैक्ट्री विधि का आह्वान करने के बाद अपने सेम पर कंटेनर कॉलिंग सेटर विधियों द्वारा पूरा किया जाता है।

public class Triangle{

 private String type;

 public String getType(){
    return type;
  }
 public void setType(String type){          //setter injection
    this.type = type;
  }
 }

<!-- setter injection -->
 <bean id="triangle" class="com.test.dependencyInjection.Triangle">
        <property name="type" value="equivialteral"/>

नोट: यह वैकल्पिक निर्भरताओं के लिए अनिवार्य निर्भरताओं और सेटर्स के लिए कन्स्ट्रक्टर तर्कों का उपयोग करने के लिए अंगूठे का एक अच्छा नियम है। ध्यान दें कि यदि हम एक सेटर पर @ आवश्यक मात्रा में एनोटेशन के आधार पर एनोटेशन का उपयोग करते हैं तो सेटर्स को आवश्यक निर्भरताओं के रूप में उपयोग करने के लिए उपयोग किया जा सकता है।


अब तक की सबसे अच्छी परिभाषा जेम्स शोर द्वारा मिली है:

"निर्भरता इंजेक्शन" 5-प्रतिशत अवधारणा के लिए 25-डॉलर का कार्यकाल है। [...] निर्भरता इंजेक्शन का अर्थ है ऑब्जेक्ट को इसके आवृत्ति चर। [...]।

मार्टिन फाउलर का एक लेख है जो उपयोगी साबित हो सकता है।

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

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


आइए कार और इंजन कक्षाओं के साथ सरल उदाहरण आज़माएं, किसी भी कार को कम से कम अभी तक कहीं भी जाने के लिए एक इंजन की आवश्यकता है। तो नीचे निर्भरता इंजेक्शन के बिना कोड कैसे दिखाई देगा।

public class Car
{
    public Car()
    {
        GasEngine engine = new GasEngine();
        engine.Start();
    }
}

public class GasEngine
{
    public void Start()
    {
        Console.WriteLine("I use gas as my fuel!");
    }
}

और कार वर्ग को तुरंत चालू करने के लिए हम अगले कोड का उपयोग करेंगे:

Car car = new Car();

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

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

    public interface IEngine
    {
        void Start();
    }

    public class GasEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I use gas as my fuel!");
        }
    }

    public class ElectricityEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I am electrocar");
        }
    }

    public class Car
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)
        {
            _engine = engine;
        }

        public void Run()
        {
            _engine.Start();
        }
    }

अब हमारी कार कक्षा केवल आईंजिन इंटरफेस पर निर्भर है, न कि इंजन के एक विशिष्ट कार्यान्वयन। अब, एकमात्र चाल यह है कि हम कार का एक उदाहरण कैसे बनाते हैं और इसे एक वास्तविक कंक्रीट इंजन क्लास जैसे गैसइंजिन या इलेक्ट्रिकइंजिन देते हैं। यही वह जगह है जहां निर्भरता इंजेक्शन आता है।

   Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

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

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

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

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

अद्यतन: हाल ही में जूली लर्मन से ईएफ कोर के बारे में पाठ्यक्रम देखा और डीआई के बारे में अपनी छोटी परिभाषा भी पसंद की।

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


आइए कल्पना करें कि आप मछली पकड़ना चाहते हैं:

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

  • निर्भरता इंजेक्शन के साथ, कोई और सभी तैयारी का ख्याल रखता है और आपके लिए आवश्यक उपकरण उपलब्ध कराता है। आप नाव (मछली पकड़ने की छड़ी और चारा) प्राप्त करने के लिए तैयार ("इंजेक्शन") प्राप्त करेंगे - सभी उपयोग करने के लिए तैयार हैं।


पैरामीटरयुक्त कन्स्ट्रक्टर और सार्वजनिक सेटर्स का उपयोग करके "निर्भरता इंजेक्शन" का मतलब सिर्फ नहीं है?

जेम्स शोर का लेख तुलना के लिए निम्नलिखित उदाहरण दिखाता है

निर्भरता इंजेक्शन के बिना निर्माता:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example() { 
    myDatabase = new DatabaseThingie(); 
  } 

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
} 

निर्भरता इंजेक्शन के साथ निर्माता:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example(DatabaseThingie useThisDatabaseInstead) { 
    myDatabase = useThisDatabaseInstead; 
  }

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
}

स्वीकार्य उत्तर एक अच्छा है - लेकिन मैं इसमें जोड़ना चाहता हूं कि डीआई कोड में हार्डकोडेड स्थिरांक से बचने वाले क्लासिक की तरह बहुत अधिक है।

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

DI ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग की दुनिया में समान है। स्थिर अक्षर के बजाय वहां मौजूद मूल्य पूरे ऑब्जेक्ट्स हैं - लेकिन क्लास कोड से उन्हें बनाने वाले कोड को स्थानांतरित करने का कारण समान है - ऑब्जेक्ट्स अक्सर उपयोग करने वाले कोड को अधिक बार बदलते हैं। एक महत्वपूर्ण मामला जहां इस तरह के बदलाव की आवश्यकता है परीक्षण है।


ढीले युग्मन के मामले में मुझे यह हास्यास्पद उदाहरण मिला:

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

उदाहरण के लिए, एक Car वस्तु पर विचार करें।

एक Car चलाने के लिए पहियों, इंजन, ईंधन, बैटरी, आदि पर निर्भर करती है। परंपरागत रूप से हम Car वस्तु की परिभाषा के साथ इस तरह के निर्भर वस्तुओं के ब्रांड को परिभाषित करते हैं।

निर्भरता इंजेक्शन के बिना (डीआई):

class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

यहां, Car वस्तु निर्भर वस्तुओं को बनाने के लिए ज़िम्मेदार है।

क्या होगा यदि हम अपने आश्रित वस्तु के प्रकार को बदलना चाहते हैं - Wheel कहें - शुरुआती NepaliRubberWheel() बाद? हमें चीनी ऑब्जेक्ट की अपनी नई निर्भरता के साथ कार ऑब्जेक्ट को फिर से बनाना होगा, लेकिन ChineseRubberWheel() निर्माता ही ऐसा कर सकता है।

तो Dependency Injection हमें क्या करता है ...?

निर्भरता इंजेक्शन का उपयोग करते समय, वस्तुओं को संकलित समय (कार निर्माण समय) के बजाए रन पर समय पर निर्भर करता है । ताकि जब भी हम चाहते हैं हम अब Wheel बदल सकते हैं। यहां, dependency ( wheel ) को रन टाइम पर Car में इंजेक्शन दिया जा सकता है।

निर्भरता इंजेक्शन का उपयोग करने के बाद:

यहां, हम रनटाइम पर निर्भरता (व्हील और बैटरी) इंजेक्शन कर रहे हैं। इसलिए शब्द: निर्भरता इंजेक्शन।

class Car{
  private Wheel wh = [Inject an Instance of Wheel (dependency of car) at runtime]
  private Battery bt = [Inject an Instance of Battery (dependency of car) at runtime]
  Car(Wheel wh,Battery bt) {
      this.wh = wh;
      this.bt = bt;
  }
  //Or we can have setters
  void setWheel(Wheel wh) {
      this.wh = wh;
  }
}

स्रोत: निर्भरता इंजेक्शन को समझना


उपरोक्त सभी उत्तर अच्छे हैं, मेरा उद्देश्य अवधारणा को सरल तरीके से समझाना है ताकि प्रोग्रामिंग ज्ञान के बिना कोई भी अवधारणा को समझ सके

निर्भरता इंजेक्शन डिजाइन पैटर्न में से एक है जो जटिल प्रणाली को सरल तरीके से बनाने में हमारी सहायता करता है।

हम अपने दैनिक जीवन में इस पैटर्न के विभिन्न प्रकार के आवेदन देख सकते हैं। कुछ उदाहरण टेप रिकॉर्डर, वीसीडी, सीडी ड्राइव इत्यादि हैं।

उपर्युक्त छवि 20 वीं शताब्दी के मध्य में रीयल-टू-रील पोर्टेबल टेप रिकॉर्डर की एक छवि है। Source

एक टेप रिकॉर्डर मशीन का प्राथमिक इरादा रिकॉर्ड या प्लेबैक ध्वनि है।

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

  1. हम मशीन के अंदर रील रख सकते हैं
  2. हम रील के लिए एक हुक प्रदान कर सकते हैं जहां इसे रखा जा सकता है।

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

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

निर्भरता इंजेक्शन का उपयोग करके हमने प्राप्त मुख्य लाभ।

  • उच्च संयोजन और ढीला युग्मन।
  • बाहरी निर्भरता और केवल जिम्मेदारी पर देख रहे हैं।
  • चीजों को घटकों के रूप में बनाना और उच्च क्षमता वाले बड़े सिस्टम बनाने के लिए गठबंधन करना।
  • यह उच्च गुणवत्ता वाले घटकों को विकसित करने में मदद करता है क्योंकि वे स्वतंत्र रूप से विकसित होते हैं, उनका उचित परीक्षण किया जाता है।
  • यदि कोई विफल रहता है तो यह घटक को दूसरे के साथ बदलने में मदद करता है।

अब एक दिन ये अवधारणा प्रोग्रामिंग दुनिया में प्रसिद्ध ढांचे के आधार बनाती है। वसंत कोणीय आदि इस अवधारणा के शीर्ष पर स्थित प्रसिद्ध सॉफ्टवेयर ढांचे हैं

निर्भरता इंजेक्शन एक ऐसी पद्धति है जो ऑब्जेक्ट्स के उदाहरण बनाने के लिए उपयोग की जाती है जो अन्य ऑब्जेक्ट्स संकलित समय पर बिना जानने के भरोसा करते हैं कि कक्षा का उपयोग उस कार्यक्षमता को प्रदान करने के लिए किया जाएगा या किसी ऑब्जेक्ट को इंजेक्शन गुणों का तरीका केवल निर्भरता इंजेक्शन कहा जाता है।

निर्भरता इंजेक्शन के लिए उदाहरण

पहले हम इस तरह कोड लिख रहे हैं

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

निर्भरता इंजेक्शन के साथ, निर्भरता इंजेक्टर हमारे लिए तत्कालता को हटा देगा

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

आप भी पढ़ सकते हैं

नियंत्रण और निर्भरता इंजेक्शन के विचलन के बीच अंतर


निर्भरता इंजेक्शन " नियंत्रण में उलटा " सिद्धांत के कार्यान्वयन का एक प्रकार है जिस पर फ्रेमवर्क बिल्डिंग आधारित है।

गोफ के "डिजाइन पैटर्न" में बताए गए ढांचे वे वर्ग हैं जो मुख्य नियंत्रण प्रवाह तर्क को कार्यान्वित करने के लिए डेवलपर को बढ़ाते हैं, इस तरह फ्रेमवर्क को नियंत्रण सिद्धांत के उलझन का एहसास होता है।

एक तकनीक के रूप में लागू करने का एक तरीका, और वर्ग पदानुक्रम के रूप में नहीं, यह आईओसी सिद्धांत यह केवल निर्भरता इंजेक्शन है।

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

कक्षा के उदाहरण " निर्भरता " हैं, संदर्भ के माध्यम से कक्षा के उदाहरण के साथ कॉलिंग घटक के बाहरी बाध्यकारी यह " इंजेक्शन " है।

जाहिर है आप इस तकनीक को ओओपी बिंदु से देखना चाहते हैं, उदाहरण के लिए कन्स्ट्रक्टर इंजेक्शन , सेटर इंजेक्शन , इंटरफ़ेस इंजेक्शन देखें

किसी ऑब्जेक्ट को रेफरी मैच के कार्य को पूरा करने के लिए किसी तीसरे पक्ष को प्रतिनिधि बनाना बहुत उपयोगी होता है जब आप एक ऐसे घटक को पूरी तरह से अलग करना चाहते हैं जिसके लिए समान सेवाओं के कार्यान्वयन से कुछ सेवाओं की आवश्यकता होती है।

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


निर्भरता इंजेक्शन और निर्भरता इंजेक्शन कंटेनर के बारे में This सबसे सरल स्पष्टीकरण मैंने कभी देखा है:

निर्भरता इंजेक्शन के बिना

  • आवेदन को फू (उदाहरण के लिए एक नियंत्रक) की आवश्यकता है, इसलिए:
  • आवेदन फू बनाता है
  • आवेदन फू कॉल करता है
    • फू को बार की आवश्यकता है (उदाहरण के लिए एक सेवा), तो:
    • फू बार बनाता है
    • फू बार बार कहते हैं
      • बार को बिम की जरूरत है (एक सेवा, एक भंडार, ...), तो:
      • बार बिम बनाता है
      • बार कुछ करता है

निर्भरता इंजेक्शन के साथ

  • आवेदन को फू की जरूरत है, जिसे बार की आवश्यकता है, जिसे बिम की आवश्यकता है, इसलिए:
  • आवेदन बिम बनाता है
  • आवेदन बार बनाता है और इसे बिम देता है
  • आवेदन फू बनाता है और इसे बार देता है
  • आवेदन फू कॉल करता है
    • फू बार बार कहते हैं
      • बार कुछ करता है

एक निर्भरता इंजेक्शन कंटेनर का उपयोग करना

  • एप्लिकेशन को फू की आवश्यकता है:
  • आवेदन कंटेनर से फू हो जाता है, इसलिए:
    • कंटेनर बिम बनाता है
    • कंटेनर बार बनाता है और इसे बिम देता है
    • कंटेनर फू बनाता है और इसे बार देता है
  • आवेदन फू कॉल करता है
    • फू बार बार कहते हैं
      • बार कुछ करता है

निर्भरता इंजेक्शन और निर्भरता इंजेक्शन कंटेनर अलग-अलग चीजें हैं:

  • निर्भरता इंजेक्शन बेहतर कोड लिखने का एक तरीका है
  • एक डी कंटेनर निर्भरता इंजेक्शन में मदद करने के लिए एक उपकरण है

निर्भरता इंजेक्शन करने के लिए आपको कंटेनर की आवश्यकता नहीं है। हालांकि एक कंटेनर आपकी मदद कर सकता है।


मुझे लगता है क्योंकि सभी ने DI के लिए लिखा है, मुझे कुछ प्रश्न पूछने दें ..

  1. जब आपके पास DI की कॉन्फ़िगरेशन हो, जहां सभी वास्तविक कार्यान्वयन (इंटरफेस नहीं) जिन्हें कक्षा में इंजेक्शन दिया जा रहा है (उदाहरण के लिए नियंत्रक को सेवाएं) क्यों यह कुछ प्रकार की हार्ड-कोडिंग नहीं है?
  2. अगर मैं ऑब्जेक्ट को रनटाइम पर बदलना चाहता हूं तो क्या होगा? उदाहरण के लिए, मेरी कॉन्फ़िगरेशन पहले से ही कहती है जब मैं MyController को तुरंत चालू करता हूं, FileLogger के लिए ILogger के रूप में इंजेक्ट करता हूं। लेकिन मैं डेटाबेस लॉगर इंजेक्ट करना चाहता हूं।
  3. हर बार जब मैं अपनी एसीलास की जरूरतों को बदलना चाहता हूं, तो मुझे अब दो स्थानों पर देखना होगा - कक्षा स्वयं और कॉन्फ़िगरेशन फ़ाइल। यह जीवन को कैसे आसान बनाता है?
  4. अगर एसीलास की अपरिपक्वता इंजेक्शन नहीं दी जाती है, तो क्या इसे मजाक करना मुश्किल है?
  5. पहले प्रश्न पर वापस जा रहे हैं। यदि नई ऑब्जेक्ट () का उपयोग करना बुरा है, तो हम कार्यान्वयन कैसे इंजेक्ट करते हैं, इंटरफ़ेस नहीं? मुझे लगता है कि आप में से बहुत से लोग कह रहे हैं कि हम वास्तव में इंटरफ़ेस इंजेक्शन कर रहे हैं लेकिन कॉन्फ़िगरेशन आपको उस इंटरफ़ेस के कार्यान्वयन को निर्दिष्ट करता है .. रनटाइम पर नहीं .. यह संकलन समय के दौरान हार्डकोड किया गया है।

यह उत्तर @ एडम एन पोस्ट पर आधारित है।

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

संपादित करें

डीआई पर मारिया मारिया अरन्ज़ द्वारा एक अच्छी टिप्पणी

डी निर्भरता की दिशा निर्धारित करने और किसी भी गोंद कोड लिखने के लिए किसी भी आवश्यकता को हटाकर एकजुटता बढ़ाता है।

असत्य। निर्भरताओं की दिशा एक्सएमएल रूप में या एनोटेशन के रूप में है, आपकी निर्भरता एक्सएमएल कोड और एनोटेशन के रूप में लिखी जाती है। एक्सएमएल और एनोटेशन स्रोत कोड हैं।

DI आपके सभी घटकों को मॉड्यूलर (यानी प्रतिलिपि बनाने योग्य) बनाकर युग्मन को कम करता है और एक दूसरे के लिए अच्छी तरह परिभाषित इंटरफेस करता है।

असत्य। इंटरफ़ेस के आधार पर आपको मॉड्यूलर कोड बनाने के लिए डीआई फ्रेमवर्क की आवश्यकता नहीं है।

बदलने योग्य के बारे में: एक बहुत ही सरल .properties संग्रह और कक्षा के साथ .forName आप परिभाषित कर सकते हैं कि कक्षाएं बदल सकती हैं। यदि आपके कोड का कोई भी वर्ग बदला जा सकता है, तो जावा आपके लिए नहीं है, एक स्क्रिप्टिंग भाषा का उपयोग करें। वैसे: एनोटेशन को बिना किसी संकलन के बदला जा सकता है।

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


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

"निर्भरता इंजेक्शन" (डीआई) को "नियंत्रण का उलटा" (आईओसी) भी कहा जाता है, जिसे इस ढीले युग्मन को प्रोत्साहित करने के लिए एक तकनीक के रूप में उपयोग किया जा सकता है।

डीआई को लागू करने के लिए दो प्राथमिक दृष्टिकोण हैं:

  1. कन्स्ट्रक्टर इंजेक्शन
  2. सेटर इंजेक्शन

कन्स्ट्रक्टर इंजेक्शन

यह अपने कन्स्ट्रक्टर को ऑब्जेक्ट निर्भरताओं को पारित करने की तकनीक है।

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

सेटर इंजेक्शन

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

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

  1. एक विरासत वर्ग के निर्माता को संशोधित किए बिना निर्भर निर्भरता इंजेक्शन का समर्थन करना।
  2. महंगी संसाधनों या सेवाओं को जितनी देर हो सके और केवल तभी बनाया जा सकता है जब आवश्यक हो।

यहां बताया गया है कि उपरोक्त कोड कैसा दिखता है:

public class Person {
    public Person() {}

    public IDAO Address {
        set { addressdao = value; }
        get {
            if (addressdao == null)
              throw new MemberAccessException("addressdao" +
                             " has not been initialized");
            return addressdao;
        }
    }

    public Address GetAddress() {
       // ... code that uses the addressdao object
       // to fetch address details from the datasource ...
    }

    // Should not be called directly;
    // use the public property instead
    private IDAO addressdao;

निर्भरता इंजेक्शन (डीआई) का पूरा बिंदु एप्लिकेशन स्रोत कोड को स्वच्छ और स्थिर रखना है :

  • निर्भरता प्रारंभिक कोड की सफाई
  • निर्भरता के बावजूद स्थिर

व्यावहारिक रूप से, प्रत्येक डिज़ाइन पैटर्न भविष्य में परिवर्तनों को न्यूनतम फ़ाइलों को प्रभावित करने के लिए चिंताओं को अलग करता है।

डीआई का विशिष्ट डोमेन निर्भरता विन्यास और प्रारंभिकरण का प्रतिनिधिमंडल है।

उदाहरण: शैल स्क्रिप्ट के साथ DI

यदि आप कभी-कभी जावा के बाहर काम करते हैं, तो याद रखें कि sourceकई स्क्रिप्टिंग भाषाओं (शेल, टीसीएल, इत्यादि, या यहां तक importकि पाइथन में भी इस उद्देश्य के लिए दुरुपयोग किया जाता है) में उपयोग किया जाता है।

सरल dependent.shलिपि पर विचार करें :

#!/bin/sh
# Dependent
touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

स्क्रिप्ट निर्भर है: यह सफलतापूर्वक निष्पादित नहीं होगा ( archive_filesपरिभाषित नहीं है)।

आप कार्यान्वयन स्क्रिप्ट archive_filesमें परिभाषित archive_files_zip.shकरते हैं ( zipइस मामले में उपयोग करके ):

#!/bin/sh
# Dependency
function archive_files {
    zip files.zip "[email protected]"
}

sourceसीधे निर्भर व्यक्ति में कार्यान्वयन स्क्रिप्ट के बजाय , आप injector.sh"कंटेनर" का उपयोग करते हैं जो "घटकों" दोनों को लपेटता है:

#!/bin/sh 
# Injector
source ./archive_files_zip.sh
source ./dependent.sh

archive_files निर्भरता सिर्फ कर दिया गया है इंजेक्शन में निर्भर स्क्रिप्ट।

आप इंजेक्शन निर्भरता प्राप्त कर सकते हैं जो archive_filesउपयोग tarया लागू करता है xz

उदाहरण: DI को हटा रहा है

यदि dependent.shस्क्रिप्ट सीधे निर्भरता का उपयोग करती है, तो दृष्टिकोण को निर्भरता लुकअप कहा जाएगा (जो निर्भरता इंजेक्शन के विपरीत है ):

#!/bin/sh
# Dependent

# dependency look-up
source ./archive_files_zip.sh

touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

अब समस्या यह है कि निर्भर "घटक" को प्रारंभिकरण करना है।

"घटक" का स्रोत कोड न तो साफ और न ही स्थिर है क्योंकि निर्भरताओं के प्रारंभ में प्रत्येक बदलाव के लिए "घटकों" की स्रोत कोड फ़ाइल के लिए भी नई रिलीज की आवश्यकता होती है।

आखरी श्ब्द

डी को जावा ढांचे में काफी हद तक जोर दिया और लोकप्रिय नहीं किया गया है।

लेकिन यह चिंताओं को विभाजित करने के लिए एक सामान्य दृष्टिकोण है:

  • आवेदन विकास ( एकल स्रोत कोड रिलीज जीवन चक्र)
  • आवेदन परिनियोजन ( स्वतंत्र जीवनसाथी के साथ कई लक्षित वातावरण)

केवल निर्भरता लुकअप के साथ कॉन्फ़िगरेशन का उपयोग करने में मदद नहीं होती है क्योंकि कॉन्फ़िगरेशन पैरामीटर की संख्या प्रति निर्भरता (जैसे नया प्रमाणीकरण प्रकार) बदल सकती है साथ ही समर्थित प्रकार की निर्भरताओं की संख्या (जैसे नया डेटाबेस प्रकार) बदल सकती है।


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

पुस्तक का इंटरफ़ेस:

package com.deepam.hidden;

public interface BookInterface {

public BookInterface setHeight(int height);
public BookInterface setPages(int pages);   
public int getHeight();
public int getPages();  

public String toString();
}

इसके बाद हमारे पास कई प्रकार की किताबें हो सकती हैं; एक प्रकार काल्पनिक है:

package com.deepam.hidden;

public class FictionBook implements BookInterface {
int height = 0; // height in cm
int pages = 0; // number of pages

/** constructor */
public FictionBook() {
    // TODO Auto-generated constructor stub
}

@Override
public FictionBook setHeight(int height) {
  this.height = height;
  return this;
}

@Override
public FictionBook setPages(int pages) {
  this.pages = pages;
  return this;      
}

@Override
public int getHeight() {
    // TODO Auto-generated method stub
    return height;
}

@Override
public int getPages() {
    // TODO Auto-generated method stub
    return pages;
}

@Override
public String toString(){
    return ("height: " + height + ", " + "pages: " + pages);
}
}

अब ग्राहक पुस्तक के साथ सहयोग कर सकते हैं:

package com.deepam.hidden;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Subscriber {
BookInterface book;

/** constructor*/
public Subscriber() {
    // TODO Auto-generated constructor stub
}

// injection I
public void setBook(BookInterface book) {
    this.book = book;
}

// injection II
public BookInterface setBook(String bookName) {
    try {
        Class<?> cl = Class.forName(bookName);
        Constructor<?> constructor = cl.getConstructor(); // use it for parameters in constructor
        BookInterface book = (BookInterface) constructor.newInstance();
        //book = (BookInterface) Class.forName(bookName).newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    return book;
}

public BookInterface getBook() {
  return book;
}

public static void main(String[] args) {

}

}

सभी तीन वर्गों को इसके अपने कार्यान्वयन के लिए छुपाया जा सकता है। अब हम DI के लिए इस कोड का उपयोग कर सकते हैं:

package com.deepam.implement;

import com.deepam.hidden.Subscriber;
import com.deepam.hidden.FictionBook;

public class CallHiddenImplBook {

public CallHiddenImplBook() {
    // TODO Auto-generated constructor stub
}

public void doIt() {
    Subscriber ab = new Subscriber();

    // injection I
    FictionBook bookI = new FictionBook();
    bookI.setHeight(30); // cm
    bookI.setPages(250);
    ab.setBook(bookI); // inject
    System.out.println("injection I " + ab.getBook().toString());

    // injection II
    FictionBook bookII = ((FictionBook) ab.setBook("com.deepam.hidden.FictionBook")).setHeight(5).setPages(108); // inject and set
    System.out.println("injection II " + ab.getBook().toString());      
}

public static void main(String[] args) {
    CallHiddenImplBook kh = new CallHiddenImplBook();
    kh.doIt();
}
}

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


निर्भरता इंजेक्शन अवधारणा को समझने के लिए सरल बनाना। आइए बल्ब को टॉगल (चालू / बंद) करने के लिए स्विच बटन का एक उदाहरण लें।

निर्भरता इंजेक्शन के बिना

स्विच को पहले से पता होना चाहिए कि मैं किस बल्ब से जुड़ा हूं (हार्ड-कोडेड निर्भरता)। इसलिए,

स्विच -> स्थायी बुलब // स्विच स्थायी बल्ब से सीधे जुड़ा हुआ है, परीक्षण आसानी से संभव नहीं है

Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}

निर्भरता इंजेक्शन के साथ

केवल स्विच ही जानता है कि मुझे जो भी बल्ब पास किया गया है उसे चालू / बंद करने की आवश्यकता है। इसलिए,

स्विच -> बल्ब 1 या बल्ब 2 या नाइटबुल (इंजेक्शन निर्भरता)

Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}

स्विच और बल्ब के लिए जेम्स उदाहरण संशोधित करना :

public class SwitchTest { 
  TestToggleBulb() { 
    MockBulb mockbulb = new MockBulb(); 

    // MockBulb is a subclass of Bulb, so we can 
    // "inject" it here: 
    Switch switch = new Switch(mockBulb); 

    switch.ToggleBulb(); 
    mockBulb.AssertToggleWasCalled(); 
  } 
}

public class Switch { 
  private Bulb myBulb; 

  public Switch() { 
    myBulb = new Bulb(); 
  } 

  public Switch(Bulb useThisBulbInstead) { 
    myBulb = useThisBulbInstead; 
  } 

  public void ToggleBulb() { 
    ... 
    myBulb.Toggle(); 
    ... 
  } 
}`

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

दुर्भाग्यवश बुरा हिस्सा यह है कि कुछ लोगों ने माना है कि आपको निर्भरता obfuscation करने के लिए एक विशेष ढांचे की आवश्यकता है और यदि आप इसे करने के लिए एक विशेष रूपरेखा का उपयोग नहीं करना चुनते हैं तो आप किसी भी तरह 'कम' प्रोग्रामर हैं। कई अन्य लोगों द्वारा विश्वास किया जाने वाला एक और बेहद परेशान मिथक यह है कि निर्भरता इंजेक्शन निर्भरता obfuscation प्राप्त करने का एकमात्र तरीका है। यह राक्षसी और ऐतिहासिक रूप से और स्पष्ट रूप से 100% गलत है लेकिन आपको कुछ लोगों को यह विश्वास करने में परेशानी होगी कि आपकी निर्भरता के लिए निर्भरता इंजेक्शन के विकल्प हैं।

प्रोग्रामर ने वर्षों के लिए निर्भरता obfuscation आवश्यकता को समझ लिया है और निर्भरता इंजेक्शन की कल्पना के पहले और बाद में कई वैकल्पिक समाधान विकसित किए गए हैं। वहाँ फैक्टरी पैटर्न हैं लेकिन वहां भी जहां एक विशेष उदाहरण के लिए कोई इंजेक्शन की जरूरत है कई विकल्प ThreadLocal का उपयोग कर रहे हैं - निर्भरता को प्रभावी ढंग से धागा जो वस्तु उपलब्ध बनाने को लाभ मिलता है में इंजेक्ट किया जाता (सुविधा के स्थिर गेटर विधियों के माध्यम से) के लिए किसी भीकक्षा जिसकी आवश्यकता होती है उसे कक्षाओं में एनोटेशन जोड़ने के बिना इसकी आवश्यकता होती है और इसे बनाने के लिए जटिल एक्सएमएल 'गोंद' स्थापित किया जाता है। जब आपकी निर्भरताओं को दृढ़ता (जेपीए / जेडीओ या जो भी हो) के लिए जरूरी है, तो यह आपको 'ट्रैनैपरेंट दृढ़ता' को अधिक आसान और डोमेन मॉडल और व्यावसायिक मॉडल कक्षाओं को पूरी तरह से पीओजेओ (यानी कोई फ्रेमवर्क विशिष्ट / एनोटेशन में लॉक) के साथ प्राप्त करने की अनुमति देता है।


बुक अप्रेस से .pring.Persistence.with.Hibernate.Oct.2010

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


मुझे पता है कि पहले से ही कई जवाब हैं, लेकिन मुझे यह बहुत उपयोगी पाया गया: http://tutorials.jenkov.com/dependency-injection/index.html

कोई निर्भरता नहीं:

Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();

निर्भरता:

public class Client {
    Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

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


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

Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();

हम बस निर्माता को गुजरने वाले पैरामीटर कहते हैं। कन्स्ट्रक्टरों का आविष्कार होने के बाद से हम नियमित रूप से ऐसा कर रहे हैं।

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

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

public class Injector {
    public static Service provideService(){
        return new Service();
    }

    public static IDatabase provideDatatBase(){
        return new SqliteDatabase();
    }
    public static ObjectA provideObjectA(){
        return new ObjectA(provideService(...));
    }
}

एक करने से पहले

Service service = Injector.provideService();

"मेक बार" टाइप करने वाले व्यक्ति को यह जानने की आवश्यकता नहीं है कि बार foo पर निर्भर करता है। "मेक बार" और जीसीसी के बीच निर्भरता इंजेक्शन दी गई थी।

मध्यवर्ती स्तर का मुख्य उद्देश्य केवल कन्स्ट्रक्टर को निर्भरता में पारित नहीं करना है, बल्कि सभी निर्भरताओं को केवल एक ही स्थान पर सूचीबद्ध करना है , और उन्हें कोडर से छिपाना है (कोडर उन्हें प्रदान करने के लिए नहीं)।

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


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

डी के लिए छोटा, निर्भर घटक को लाने के लिए घटकों पर एक आम अतिरिक्त ज़िम्मेदारी (बोझ) को हटाने के लिए एक तकनीक है, जिससे उन्हें प्रदान किया जा सके।

DI आपको एकल जिम्मेदारी (एसआर) सिद्धांत के करीब लाता है, जैसे surgeon who can concentrate on surgery

डीआई का उपयोग कब करें: मैं लगभग सभी उत्पादन परियोजनाओं (छोटे / बड़े) में डीआई का उपयोग करने की सिफारिश करता हूं, खासकर कभी भी बदलते कारोबारी माहौल में :)

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







terminology