रणनीति पैटर्न और निर्भरता इंजेक्शन के बीच अंतर क्या है?


95

रणनीति पैटर्न और निर्भरता इंजेक्शन दोनों ही हमें रन टाइम पर ऑब्जेक्ट सेट / इंजेक्ट करने की अनुमति देते हैं। रणनीति पैटर्न और निर्भरता इंजेक्शन के बीच अंतर क्या है?


रणनीति पैटर्न निर्भरता इंजेक्शन का उपयोग कर सकती है
TechWisdom

जवाबों:


107

DI और रणनीति एक ही तरह से काम करते हैं, लेकिन रणनीति का उपयोग अधिक बारीक और अल्पकालिक निर्भरता के लिए किया जाता है।

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

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

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

DI के साथ आप अपने कार्यक्रम को अन्य कारणों से विघटित कर सकते हैं, केवल कार्यान्वयन के कुछ हिस्सों को सक्षम करने के लिए। केवल एक कार्यान्वयन के साथ DI में उपयोग किया जाने वाला इंटरफ़ेस बहुत आम है। केवल एक ठोस कार्यान्वयन (कभी) के साथ एक "रणनीति" एक वास्तविक समस्या नहीं है, लेकिन संभवतः DI के करीब है।


DI में केवल एक कार्यान्वयन के साथ उपयोग किया जाने वाला इंटरफ़ेस बहुत सामान्य है - तो इस विशेष मामले में DI क्या है?
कल्पेश सोनी

3
यह उद्धरण मूल रूप से यह सब समझाता है:in a DI scenario it is more unusual that the dependencies of objects change during their lifetimes, while this is not uncommon with Strategy
सर्गेई Telshevsky

रणनीति: कक्षाएं डिज़ाइन की जाती हैं ताकि उन्हें रन-टाइम पर एक एल्गोरिथ्म के साथ कॉन्फ़िगर किया जा सके। DI: ऐसी कक्षाओं को एक एल्गोरिथ्म (एक रणनीति वस्तु) मिलती है जो रन-टाइम पर इंजेक्ट की जाती है। Go3 डिजाइन पैटर्न मेमोरी से w3sdesign.com पर
22

39

अंतर यह है कि वे क्या हासिल करने की कोशिश कर रहे हैं। रणनीति पैटर्न उन स्थितियों में उपयोग किया जाता है जहां आप जानते हैं कि आप कार्यान्वयन को स्वैप करना चाहते हैं। एक उदाहरण के रूप में, आप अलग-अलग तरीकों से डेटा प्रारूपित करना चाह सकते हैं - आप एक XML फॉर्मेटर या CSV फॉर्मैटर इत्यादि को स्वैप करने के लिए रणनीति पैटर्न का उपयोग कर सकते हैं।

निर्भरता इंजेक्शन अलग है कि उपयोगकर्ता रनटाइम व्यवहार को बदलने की कोशिश नहीं कर रहा है। ऊपर दिए गए उदाहरण के बाद, हम एक XML एक्सपोर्ट प्रोग्राम बना सकते हैं जो XML फॉर्मैटर का उपयोग करता है। इस तरह कोड को संरचित करने के बजाय:

public class DataExporter() {
  XMLFormatter formatter = new XMLFormatter();
}

आप कंस्ट्रक्टर में फ़ॉर्मेटर को 'इंजेक्ट' करेंगे:

public class DataExporter {
  IFormatter formatter = null;

  public DataExporter(IDataFormatter dataFormatter) {
    this.formatter = dataFormatter;
  }
}

DataExporter exporter = new DataExporter(new XMLFormatter());

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

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


28

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

यह कहना जोखिम भरा होगा कि DI सिर्फ एक बदला हुआ रणनीति पैटर्न है क्योंकि IMO वास्तव में रणनीति पैटर्न क्या है, इसे पतला करने के लिए शुरू होता है।


2
मुझे लगता है कि मैं आपकी समझ को समझता हूं, लेकिन मैं इसे शब्दों में सही तरीके से नहीं लिख सकता ... इसलिए आपका कहना डीआई एक कार्यान्वयन पैटर्न का अधिक है जबकि रणनीति एक डिजाइन पैटर्न का अधिक है, और रणनीति को लागू करने का एक तरीका डीआई के माध्यम से है?
रॉबर्ट गोल्ड

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

15

यार, निर्भरता इंजेक्शन एक अधिक सामान्य पैटर्न है, और यह अमूर्तता पर निर्भरता के बारे में है न कि सहमति और यह हर पैटर्न का एक हिस्सा है, लेकिन रणनीति पैटर्न अधिक विशिष्ट समस्या का समाधान है

यह विकिपीडिया की परिभाषा है:

डि:

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

रणनीति पैटर्न:

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

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


3
मैं विशेष रूप से आपकी व्याख्या में "दोस्त" भाग को पसंद करता हूं। :-)
जोहे जुले १19

7

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

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


रणनीति का उदाहरण:

public class Cosine {
  private CalcStrategy strat;

  // Constructor - strategy passed in as a type of DI
  public Cosine(CalcStrategy s) {
    strat = s;
  }
}

public abstract class CalcStrategy {
  public double goFigure(double angle);
}

public class RadianStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}
public class DegreeStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}

ध्यान दें कि कोई भी सार्वजनिक डेटा नहीं है जो रणनीतियों के बीच भिन्न है। न ही कोई अलग तरीका है। दोनों रणनीतियाँ समान कार्य और हस्ताक्षर साझा करती हैं।


अब निर्भरता इंजेक्शन के लिए:

public class Cosine {
  private Calc strat;

  // Constructor - Dependency Injection.
  public Cosine(Calc s) {
    strat = s;
  }
}

public class Calc {
  private int numPasses = 0;
  private double total = 0;
  private double intermediate = 0;

  public double goFigure(double angle) {
    return(...);
}

public class CalcTestDouble extends Calc {
  // NOTICE THE PUBLIC DATA.
  public int numPasses = 0;
  public double total = 0;
  public double intermediate = 0;
  public double goFigure(double angle) {
    return (...);
  }
}

उपयोग:

public CosineTest {

  @Test
  public void testGoFigure() {
    // Setup
    CalcTestDouble calc = new CalcTestDouble();
    Cosine instance = new Cosine(calc);

    // Exercise
    double actualAnswer = instance.goFigure(0.0);

    // Verify
    double tolerance = ...;
    double expectedAnswer = ...;
    assertEquals("GoFigure didn't work!", expectedAnswer,
         actualAnswer, tolerance);

    int expectedNumPasses = ...;
    assertEquals("GoFigure had wrong number passes!",
        expectedNumPasses, calc.numPasses);

    double expectedIntermediate = ...;
    assertEquals("GoFigure had wrong intermediate values!",
        expectedIntermediate, calc.intermediate, tolerance);
  }
}

अंतिम 2 चेकों पर ध्यान दें। उन्होंने परीक्षण में सार्वजनिक डेटा का उपयोग किया जो परीक्षण के तहत कक्षा में इंजेक्ट किया गया था। मैं डेटा छिपाने के सिद्धांत के कारण उत्पादन कोड के साथ ऐसा नहीं कर सका। मैं उत्पादन कोड में विशेष प्रयोजन परीक्षण कोड सम्मिलित नहीं करना चाहता था। सार्वजनिक डेटा एक अलग वर्ग में होना था।

परीक्षण डबल इंजेक्ट किया गया था। यह केवल एक रणनीति से अलग है क्योंकि यह डेटा को प्रभावित करता है और न केवल कार्य करता है।


4

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

निर्भरता इंजेक्शन न केवल किस ठोस रणनीति का उपयोग करने के लिए बल्कि ठोस रणनीति की एक आवृत्ति बनाने और इसे कॉलिंग मॉड्यूल में वापस "इंजेक्शन" करके रणनीति पैटर्न को परिष्कृत करता है। यह तब भी उपयोगी है जब केवल एक ही निर्भरता हो कि कैसे (आरंभ आदि) को प्रबंधित करने के ज्ञान के रूप में ठोस रणनीति का उदाहरण भी रणनीति ऑब्जेक्ट के भीतर छिपाया जा सकता है।


1

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


0

रणनीति आपके निर्भरता इंजेक्शन कौशल का उपयोग करने के लिए एक क्षेत्र है। निर्भरता इंजेक्शन को लागू करने के असली तरीके इस प्रकार हैं: -

  1. आयोजन
  2. एकता / संरचना मानचित्र (या प्रोग्रामेटिक) आदि की कॉन्फ़िगरेशन फ़ाइलें।
  3. एक्सटेंशन के तरीके
  4. सार फैक्टरी पैटर्न
  5. नियंत्रण पैटर्न का उलटा (रणनीति और अमूर्त कारखाने दोनों द्वारा उपयोग किया जाता है)

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

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


0

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


1
मुझे यकीन नहीं है कि मैं अनुसरण करता हूं, क्या आप इस बात पर विस्तार कर सकते हैं कि रणनीति ओपन / बंद सिद्धांत से संबंधित है और डीआई डीआईपी से कैसे संबंधित है?
एडम पार्किं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.