2008-11-01 7 views
19

मैं इस जगह पर पढ़ता हूं कि कैसे वसंत आपके कोड में इंटरफेस का उपयोग करने के लिए प्रोत्साहित करता है। मुझे यह नहीं दिख रहा है। आपके वसंत xml विन्यास में इंटरफेस की कोई धारणा नहीं है। वसंत का कौन सा हिस्सा वास्तव में आपको इंटरफेस (दस्तावेज़ों के अलावा) का उपयोग करने के लिए प्रोत्साहित करता है?वसंत और इंटरफेस

+1

DI के बारे में उठाए गए बिंदुओं के अलावा, वसंत रिमोटिंग जैसी चीजें इंटरफेस का उपयोग करने पर पूरी तरह निर्भर हैं। – Robin

+0

यह एक बहुत अच्छा सवाल है। और जैसा कि आप अब तक उत्तरों से देख सकते हैं, किसी ने भी एक विशिष्ट उत्तर नहीं दिया है। –

उत्तर

25

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

लेकिन यदि आप किसी अन्य वर्ग को इंजेक्ट करना चाहते हैं जो "समकक्ष" कार्यक्षमता प्रदान करता है, तो इंटरफ़ेस का उपयोग करके वास्तव में मदद मिलती है।

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

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

+6

जबकि आप जो कहते हैं वह सही है, यह वसंत केंद्रित नहीं है। यह जावा केंद्रित है। –

2

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

यहाँ उदाहरण के एक जोड़े हैं:

  1. आप एक वर्ग एक संसाधन से पढ़ने की जरूरत है लिख रहे हैं कहो (जैसे, फ़ाइल) है कि कई तरीके (जैसे, classpath में संदर्भित किया जा सकता है, एक यूआरएल आदि के रूप में पूर्ण फ़ाइल पथ)। आप अपनी कक्षा में org.springframework.core.io.Resource (इंटरफ़ेस) संपत्ति को परिभाषित करना चाहते हैं। फिर अपनी स्प्रिंग कॉन्फ़िगरेशन फ़ाइल में, आप बस वास्तविक कार्यान्वयन कक्षा का चयन करें (उदा।, org.springframework.core.io.ClassPathResource, org.springframework.core.io.FileSystemResource, org.springframework.core.io.UrlResource आदि)। वसंत मूल रूप से एक बेहद सामान्य कारखाने के रूप में काम कर रहा है।

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

ये उदाहरण हैं जिनके साथ मुझे व्यक्तिगत रूप से अनुभव है। मुझे यकीन है कि वहां बहुत कुछ है।

31

Dependency Inversion Principle इस अच्छी तरह से बताता है। विशेष रूप से, आकृति 4.

ए उच्च स्तरीय मॉड्यूल निम्न स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। दोनों को अवशोषण पर निर्भर होना चाहिए।

बी। सार तत्व विवरण पर निर्भर नहीं होना चाहिए। विवरण abstractions पर निर्भर होना चाहिए।

जावा में ऊपर के लिंक से उदाहरण का अनुवाद:

public class Copy { 
    private Keyboard keyboard = new Keyboard(); // concrete dependency 
    private Printer printer = new Printer(); // concrete dependency 
    public void copy() { 
     for (int c = keyboard.read(); c != KeyBoard.EOF) { 
      printer.print(c); 
     } 
    } 
} 
अब निर्भरता उलट साथ

:

public class Copy { 
    private Reader reader; // any dependency satisfying the reader interface will work 
    private Writer writer; // any dependency satisfying the writer interface will work 
    public void copy() { 
     for (int c = reader.read(); c != Reader.EOF) { 
      writer.write(c); 
     } 
    } 
    public Copy(Reader reader, Writer writer) { 
     this.reader = reader; 
     this.writer = writer; 
    } 
} 

अब Copy सिर्फ एक प्रिंटर से एक कीबोर्ड से कॉपी करने से भी अधिक का समर्थन करता है।

यह किसी भी Reader से किसी भी Writer पर अपने कोड में कोई संशोधन की आवश्यकता के बिना कॉपी करने में सक्षम है।

और अब वसंत के साथ:

<bean id="copy" class="Copy"> 
    <constructor-arg ref="reader" /> 
    <constructor-arg ref="writer" /> 
</bean> 

<bean id="reader" class="KeyboardReader" /> 
<bean id="writer" class="PrinterWriter" /> 

या शायद:

<bean id="reader" class="RemoteDeviceReader" /> 
<bean id="writer" class="DatabaseWriter" /> 
9

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

+0

मैंने यूनिट परीक्षण के दावे का समर्थन करने के लिए कोई सबूत नहीं देखा है सॉफ्टवेयर गुणवत्ता/विश्वसनीयता/गति में सुधार करता है। – Chad

+5

@ चाड आप ट्रोलिंग? – Ryan

0

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

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

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

1

इंटरफेस से प्रॉक्सी उत्पन्न करना आसान है।

यदि आप किसी भी वसंत ऐप को देखते हैं, तो आप सेवा और दृढ़ता इंटरफेस देखेंगे। यह सुनिश्चित करना कि वसंत मुहावरे निश्चित रूप से इंटरफेस के उपयोग को प्रोत्साहित करता है। यह उससे कहीं अधिक स्पष्ट नहीं मिलता है।

1

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

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

1

आप इंटरफेस उपयोग नहीं करते हैं तो आप एक autowiring विफलता जोखिम। यह प्रॉक्सी क्लास सेवा कार्यान्वयन का एक बाल वर्ग नहीं है लेकिन यह इसके सभी इंटरफेस को फिर से लागू करता है। वसंत इस बीन के उदाहरणों को स्वत: करने की कोशिश करेगा, हालांकि यह प्रॉक्सी वर्ग बीन वर्ग के साथ असंगत है। तो बीन कक्षा के साथ एक क्षेत्र घोषित करने से "असुरक्षित क्षेत्र असाइनमेंट" अपवाद हो सकते हैं।

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