निर्भरता इंजेक्शन कक्षा को यह कहने के पैटर्न को संदर्भित करता है कि क्लास को इसकी सभी निर्भरताओं को कहां से ढूंढना है, इसकी आवश्यकता के बजाय। कुछ इस तरह के
public class UserFetcher {
private final DbConnection conn =
new DbConnection("10.167.1.25", "username", "password");
public List<User> getUsers() {
return conn.fetch(...);
}
}
:
तो, उदाहरण के लिए, आप इस से जाना
public class UserFetcher {
private final DbConnection conn;
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
इस कोड है, जो विशेष रूप से उपयोगी है में युग्मन कम कर देता है इकाई परीक्षण करने के लिए अगर आप चाहते हैं UserFetcher
। अब, UserFetcher
हमेशा10.167.1.25
पर मिले डेटाबेस के विरुद्ध चलने के बजाय, आप एक परीक्षण डेटाबेस में DbConnection
में पास कर सकते हैं। या, एक तेज परीक्षण में और भी उपयोगी, आप DbConnection
के कार्यान्वयन या उप-वर्ग में पास कर सकते हैं जो किसी डेटाबेस से कनेक्ट नहीं होता है, यह केवल अनुरोधों को त्याग देता है!
हालांकि, आदिम निर्भरता इंजेक्शन की इस तरह तारों अधिक कठिन (अपनी निर्भरता के साथ एक वस्तु प्रदान करते हुए), क्योंकि आप निर्भरता गुजर साथ निर्भरता एक वैश्विक चर का उपयोग कर (या एक स्थानीय रूप से instantiated ऑब्जेक्ट) तक पहुँचने से बदल दिया है बनाता है पूरे ऑब्जेक्ट ग्राफ के माध्यम से।
एक ऐसे मामले के बारे में सोचें जहां UserFetcher
AccountManager
की निर्भरता है, जो AdminConsole
की निर्भरता है। तब AdminConsole
जरूरतों AccountManager
को DbConnection
उदाहरण पारित करने के लिए, और AccountManager
जरूरतों UserFetcher
करने के लिए इसे पारित करने के लिए ... भले ही न AdminConsole
है और न ही AccountManager
सीधे DbConnection
उपयोग करने के लिए की जरूरत है!
नियंत्रण कंटेनर का एक उलट (स्प्रिंग, Guice, आदि) स्वचालित रूप से तारों (प्रदान) निर्भरता से निर्भरता इंजेक्शन आसान बनाने के लिए करना है। ऐसा करने के लिए, आप अपने आईओसी कंटेनर को एक बार बताएं कि एक वस्तु कैसे प्रदान करें (वसंत में, इसे बीन कहा जाता है) और जब भी कोई अन्य वस्तु उस निर्भरता के लिए पूछती है, तो यह कंटेनर द्वारा प्रदान की जाएगी।
तो हमारे पिछले उदाहरण Guice के साथ इस प्रकार दिखाई देंगे, अगर हम निर्माता इंजेक्शन का इस्तेमाल किया:
public class UserFetcher {
private final DbConnection conn;
@Inject //or @Autowired for Spring
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
और हम आईओसी कंटेनर कॉन्फ़िगर करने के लिए की है। Guice में यह Module
के कार्यान्वयन के माध्यम से किया जाता है; वसंत में आप एप्लिकेशन संदर्भ को अक्सर एक्सएमएल के माध्यम से कॉन्फ़िगर करते हैं।
public class MyGuiceModule extends AbstractModule {
@Override
public void configure() {
bind(DbConnection.class).toInstance(
new DbConnection("localhost", "username", "password"));
}
}
अब जब UserFetcher
Guice या वसंत द्वारा निर्माण किया है, DbConnection
स्वचालित रूप से प्रदान की जाती है।
गुइस के पास निर्भरता इंजेक्शन के पीछे प्रेरणा पर a really good Wiki article है, और आगे एक आईओसी कंटेनर का उपयोग कर। यह सभी तरह से पढ़ने लायक है।
रणनीति पैटर्न सिर्फ निर्भरता इंजेक्शन, जहाँ आप तर्क के बजाय एक वस्तु (भले ही जावा में, तर्क एक वस्तु में समाहित किया जाएगा) इंजेक्षन की एक विशेष मामला है। यह स्वतंत्र व्यापार तर्क decoupling का एक तरीका है।
उदाहरण के लिए, अगर आप इस तरह कोड हो सकता है:
public Currency computeTotal(List<Product> products) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = beforeTax.times(1.10);
}
लेकिन क्या होगा अगर आप एक अलग बिक्री कर योजना के साथ, एक नया अधिकार क्षेत्र के लिए इस कोड का विस्तार करना चाहते थे? आप कर की गणना करने, इस तरह तर्क इंजेक्षन सकता है:
public interface TaxScheme {
public Currency applyTax(Currency beforeTax);
}
public class TenPercentTax implements TaxScheme {
public Currency applyTax(Currency beforeTax) {
return beforeTax.times(1.10);
}
}
public Currency computeTotal(List<Product> products, TaxScheme taxScheme) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = taxScheme.applyTax(beforeTax);
return afterTax;
}