2009-09-11 15 views
18

मैं सबसे प्रोग्रामिंग से संबंधित साइटों पर बयान सुनवाई रखना: एक अंतरफलक के लिएइंटरफ़ेस में प्रोग्राम करने का क्या अर्थ है?

कार्यक्रम और नहीं करने के लिए एक कार्यान्वयन

हालांकि मैं निहितार्थ समझ में नहीं आता?
उदाहरण मदद करेंगे।

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

उत्तर

34

आप शायद कुछ इस तरह के लिए देख रहे हैं? मान लें कि बाद में आप तय करते हैं कि LinkedHashSet की कार्यक्षमता का लाभ उठाने के लिए, एक लिंक्ड हैशसेट कहें, आपको एक अलग डेटा संरचना का उपयोग करने की आवश्यकता है। कोड को इस प्रकार बदला जाना चाहिए:

public static void main(String... args) { 
    // do this - declare the variable to be of type Set, which is an interface 
    Set buddies = new LinkedHashSet(); // <- change the constructor call 

    // don't do this - you declare the variable to have a fixed type 
    // this you have to change both the variable type and the constructor call 
    // HashSet buddies2 = new HashSet(); // old version 
    LinkedHashSet buddies2 = new LinkedHashSet(); 
} 

यह इतना बुरा नहीं लगता है, है ना? लेकिन क्या होगा यदि आपने गेटर्स को वैसे ही लिखा था?

public HashSet getBuddies() { 
    return buddies; 
} 

इसे भी बदला जाना होगा!

public LinkedHashSet getBuddies() { 
    return buddies; 
} 

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

public Set getBuddies() { 
    return buddies; 
} 

, एक और फायदा भी नहीं है में है कि (अच्छी तरह से कम से कम मेरे लिए) अंतर में मदद करता है मुझे एक कार्यक्रम बेहतर डिजाइन। लेकिन उम्मीद है कि मेरे उदाहरण आपको कुछ विचार देते हैं ... उम्मीद है कि इससे मदद मिलती है।

+0

वाह! यह बहुत अच्छी तरह से समझाया गया है! –

+1

धन्यवाद! खुशी है कि मैं मदद कर सकता हूं :) – weiji

+2

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

3

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

+0

यह उत्तर न तो इस पद्धति के लिए या इसके खिलाफ एक बयान है, एफवाईआई। –

5

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

उदाहरण के लिए, मॉड्यूल 1 किसी विशेष उपयोगकर्ता के लिए बैंक खाता जानकारी प्रदर्शित करने का ख्याल रखेगा, और मॉड्यूल 2 "जो भी" बैक-एंड का उपयोग किया जाता है, से बैंक खाता जानकारी प्राप्त करेगा।

संबंधित पैरामीटर के साथ कुछ प्रकार और कार्यों को परिभाषित करके, उदाहरण के लिए एक बैंक लेनदेन को परिभाषित करने वाली संरचना, और कुछ विधियों (कार्यों) जैसे GetLastTransactions (AccountNumber, NbTransactionsWanted, ArrayToReturnTheseRec) और GetBalance (AccountNumer), मॉड्यूल 1 आवश्यक जानकारी प्राप्त करने में सक्षम होगा, और चिंता न करें कि यह जानकारी कैसे संग्रहीत या गणना की जाती है या जो भी हो। इसके विपरीत, मॉड्यूल 2 परिभाषित इंटरफेस के अनुसार जानकारी प्रदान करके विधियों के कॉल का जवाब देगा, लेकिन इस बारे में चिंता नहीं करेगा कि यह जानकारी कहां प्रदर्शित की जा सकती है, मुद्रित या जो भी ...

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

यह एक एपीआई का विचार है।

1

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

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

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

4

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

+1

@ डाउनवॉटर: क्या? – jason

1

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

public static void main(String... args) { 
    // do this - declare the variable to be of type Set, which is an interface 
    Set buddies = new HashSet(); 

    // don't do this - you declare the variable to have a fixed type 
    HashSet buddies2 = new HashSet(); 
} 

क्यों यह अच्छा माना जाता है यह पहली तरीके से करना:

3

लाल 2x4 लेगो ब्लॉक लें और इसे नीले 2x4 लेगो ब्लॉक से संलग्न करें ताकि कोई दूसरे के ऊपर बैठे। अब नीले रंग के ब्लॉक को हटा दें और इसे पीले 2x4 लेगो ब्लॉक से प्रतिस्थापित करें। ध्यान दें कि संलग्न ब्लॉक के "कार्यान्वयन" के बावजूद लाल ब्लॉक को बदलने की ज़रूरत नहीं थी।

अब किसी अन्य प्रकार का ब्लॉक प्राप्त करें जो लेगो "इंटरफेस" साझा नहीं करता है। इसे लाल 2x4 लेगो से अटैच करने का प्रयास करें। ऐसा करने के लिए, आपको लेगो या अन्य ब्लॉक को बदलने की आवश्यकता होगी, शायद कुछ प्लास्टिक को काटकर या नई प्लास्टिक या गोंद जोड़कर। ध्यान दें कि "कार्यान्वयन" को बदलकर आपको इसे या ग्राहक को बदलने के लिए मजबूर होना पड़ता है।

क्लाइंट या सर्वर को बदलने के बिना कार्यान्वयन करने में सक्षम होने के नाते - यह इंटरफेस के लिए प्रोग्राम का मतलब है।

+0

+1 के लिए एक समानता – Smalltown2k

+0

+1 में लेगो के उपयोग के लिए +1 सर्वश्रेष्ठ उत्तर: डी –

1

इसका मतलब है कि आपके चर, गुण, पैरामीटर और रिटर्न प्रकारों में एक ठोस कार्यान्वयन के बजाय एक इंटरफ़ेस प्रकार होना चाहिए।

जिसका अर्थ है कि आप उदाहरण के लिए ArrayList Foo(ArrayList myList) के बजाय IEnumerable<T> Foo(IList mylist) का उपयोग करते हैं।

उपयोग कार्यान्वयन केवल जब वस्तु का निर्माण:

IList list = new ArrayList(); 

आप इस किया है, तो आप बाद में वस्तु प्रकार बदल सकते हैं हो सकता है आप बाद में LinkedList ArrayList के बजाय का उपयोग करना चाहते, यह हर जगह के बाद से कोई समस्या नहीं है अन्यथा आप इसे "IList" के रूप में संदर्भित करते हैं

7

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

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

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

मैं ओपी के प्रश्न में यदि किसी और शेयरों वाक्यांश की इस व्याख्या देखने के लिए उत्सुक हैं, या अगर मैं पूरी तरह से बंद आधार हूँ ...

+2

यह मेरी समझ भी है - एक इंटरफ़ेस के लिए प्रोग्रामिंग का अर्थ दस्तावेज़, विनिर्देश, या प्रोटोकॉल पर प्रोग्राम करना है। तो यदि आप एक इंटरफ़ेस में प्रोग्रामिंग कर रहे हैं, तो "एक्स एक्स काम" के बारे में एक चर्चा "मैंने कोशिश की है और यह काम करता है/काम नहीं करता" है, यह "मैं प्रलेखन पढ़ता हूं, और यह परमिट देता है" एक्स/मना करता है एक्स/एक्स का उल्लेख नहीं करता एक्स/एक्स के बारे में संदिग्ध है "। –

2

अन्य उत्तर के अलावा, मैं और अधिक जोड़ने:

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

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

+0

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

5

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

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

यदि आप किसी विशेष कार्यान्वयन लिए कोड जब यदि आप क्योंकि नई वस्तु एक ही तरीके का जवाब नहीं हो सकता है, अंतर्निहित अपने कोड होगा सबसे अधिक संभावना को तोड़ने आपत्ति बदलने की जरूरत है।

तो एक स्पष्ट उदाहरण डाल करने के लिए:

आप वस्तुओं आप एक Vector उपयोग करने का फैसला हो सकता है की एक संख्या पकड़ करने के लिए की जरूरत है।

आप लिखते हैं आप वेक्टर के पहले वस्तु का उपयोग करने की जरूरत है हो सकता है:

Vector items = new Vector(); 
// fill it 
Object first = items.firstElement(); 

अब तक तो अच्छा।

बाद में आप का फैसला किया है कि क्योंकि के लिए "कुछ" कारण आप कार्यान्वयन को बदलने की जरूरत

आपको पता है कि आप एक ArrayList instad उपयोग करने की आवश्यकता (मान लीजिए कि वेक्टर अत्यधिक तुल्यकालन के कारण अड़चन पैदा करता है)।

ठीक है, आप कोड टूट जाएगा ...

ArrayList items = new ArrayList(); 
// fill it 
Object first = items.firstElement(); // compile time error. 

आप नहीं कर सकते। यह लाइन और उन सभी पंक्तियों का उपयोग जो प्रथम एलिमेंट() विधि का उपयोग करेंगे तो टूट जाएंगे।

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

List items = new Vector(); 
// fill it 
Object first = items.get(0); // 

इस फार्म आप get method of Vector लिए कोडिंग में नहीं आते, लेकिन get method of List करने के लिए।

यह कैसे करना है अंतर्निहित वस्तु विधि करता है, जब तक कि यह

इस तरह "संग्रह का 0 तत्व मिल" के अनुबंध का जवाब के रूप में आप बाद में किसी अन्य कार्यान्वयन के लिए इसे बदल सकता है कोई फर्क नहीं पड़ता :

List items = new ArrayList(); // Or LinkedList or any other who implements List 
// fill it 
Object first = items.get(0); // Doesn't break 

यह नमूना अनुभवहीन लग सकता है, लेकिन आधार

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

statement.executeOracle9iSomething(); 

बनाम

statement.executeOracle11gSomething(); 

कुछ इसी तरह के जावा स्विंग के साथ होता है।

अतिरिक्त पठन:

Design Principles from Design Patterns

Effective Java Item: Refer to objects by their interfaces

(इस पुस्तक सबसे अच्छी चीजों में आप जीवन में कर सकता है में से एक खरीद - और निश्चित रूप से अगर पढ़ा -)

+0

शानदार! किताबें भी आश्चर्यजनक लगती हैं! कोड के संबंध में, हमने सूची आइटम = नए वेक्टर() से प्रोग्राम में कोड की एक पंक्ति बदल दी है; सूची आइटम = नई ArrayList(); इसलिए अंत में हमें क्लाइंट एरिया में कुछ कोड बदलना पड़ा ताकि वेक्टर से संबंधित कोड की शेष पंक्तियों को भी बदल सकें जो टूटने जा रहे हैं। मैं अभी भी महत्व को समझ नहीं पा रहा हूं। –

+1

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

16

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

प्रोग्रामर कोडिंग शुरू कर दिया। कुछ हफ्ते बाद उसने महसूस किया कि मेट्रिक्स और ग्राफ और सामान बॉस को संतुष्ट करने के लिए काफी थे, और उन्होंने अपना काम प्रस्तुत किया। बॉस ने कहा, "यह बहुत अच्छा है", लेकिन क्या यह हमारे पास इस SQL ​​डेटाबेस से व्यवसाय डेटा भी दिखा सकता है? "।

प्रोग्रामर कोडिंग पर वापस चला गया। एक्सएमएल से अपने डेटा के दौरान छिड़काव से व्यवसाय डेटा पढ़ने के लिए कोड था। उन्होंने कहा कि उन सभी के टुकड़े दुबारा लिखा, उन लोगों के साथ लपेटकर एक "अगर" हालत:

if (dataType == "XML") 
{ 
    ... read a piece of XML data ... 
} 
else 
{ 
    .. query something from the SQL database ... 
} 

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

मालिक ने जवाब दिया: "कुछ भी है कि यह प्रदान कर सकते हैं" उस पल में

, प्रोग्रामर enlightened था।

+0

अद्भुत! .. निश्चित रूप से एक प्रबुद्ध व्यक्ति द्वारा लिखित! –

+0

एर! .. लेकिन क्या आप मुझे प्रबुद्ध कर सकते हैं! ...प्रोग्रामर ने क्या किया? –

+6

उन्होंने महसूस किया कि वह डेटा स्रोत के एक एकल अमूर्तता के खिलाफ प्रोग्रामिंग द्वारा डेटा स्रोत के प्रकार के बारे में सबसे अधिक अज्ञात बना सकता है; एक इंटरफेस! नए डेटा स्रोत प्रकारों के लिए समर्थन जोड़ना इंटरफ़ेस का नया कार्यान्वयन करने का विषय बन जाता है। शेष कोड को छूना नहीं है। यह ** डेटा मैपर ** पैटर्न है। –

3

देखो, मुझे नहीं पता था कि यह जावा के लिए था, और मेरा कोड सी # पर आधारित है, लेकिन मेरा मानना ​​है कि यह बिंदु प्रदान करता है।

प्रत्येक कार में दरवाजे होते हैं।

लेकिन हर दरवाजा ऐसा ही नहीं करता है, जैसे यूके में टैक्सी दरवाजे पीछे की तरफ हैं। एक सार्वभौमिक तथ्य यह है कि वे "ओपन" और "बंद करें"।

interface IDoor 
{ 
    void Open(); 
    void Close(); 
} 

class BackwardDoor : IDoor 
{ 
    public void Open() 
    { 
     // code to make the door open the "wrong way". 
    } 

    public void Close() 
    { 
     // code to make the door close properly. 
    } 
} 

class RegularDoor : IDoor 
{ 
    public void Open() 
    { 
     // code to make the door open the "proper way" 
    } 

    public void Close() 
    { 
     // code to make the door close properly. 
    } 
} 

class RedUkTaxiDoor : BackwardDoor 
{ 
    public Color Color 
    { 
     get 
     { 
      return Color.Red; 
     } 
    } 
} 

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

class DoorRepairer 
{ 
    public void Repair(IDoor door) 
    { 
     door.Open(); 
     // Do stuff inside the car. 
     door.Close(); 
    } 
} 

रिपेयर RedUkTaxiDoor, RegularDoor और BackwardDoor को संभाल सकता है। और ट्रक के दरवाजे, लिमोसिन दरवाजे जैसे किसी अन्य प्रकार के दरवाजे।

DoorRepairer repairer = new DoorRepairer(); 

repairer.Repair(new RegularDoor()); 
repairer.Repair(new BackwardDoor()); 
repairer.Repair(new RedUkTaxiDoor()); 

सूचियों के लिए इस लागू करें, आप LinkedList, ढेर, कतार, सामान्य सूची है, और आप अपने खुद के, MyList चाहते हैं। वे सभी आईएलआईएस इंटरफेस को लागू करते हैं, जिसके लिए उन्हें जोड़ने और निकालने के लिए आवश्यक है। तो अपने वर्ग जोड़ सकते हैं या किसी भी सूची में आइटम्स को दूर करता है, तो ...

class ListAdder 
{ 
    public void PopulateWithSomething(IList list) 
    { 
     list.Add("one"); 
     list.Add("two"); 
    } 
} 

Stack stack = new Stack(); 
Queue queue = new Queue(); 

ListAdder la = new ListAdder() 
la.PopulateWithSomething(stack); 
la.PopulateWithSomething(queue); 
+0

कोई समस्या नहीं! जब तक हम समझ प्राप्त करते हैं तब तक जावा या सी # भाषा के संबंध में। धन्यवाद! –

+0

जावा में सम्मेलन दरवाजा का उपयोग करना है और इंटरफ़ेस के लिए आईडीूर नहीं है। –

2

एलन होलुब जावावर्ल्ड के लिए एक महान लेख 2003 में इस विषय Why extends is evil कहा जाता है पर लिखा था।"इंटरफ़ेस टू प्रोग्राम" कथन पर उनका लेना, जैसा कि आप अपने शीर्षक से एकत्र कर सकते हैं, यह है कि आपको खुशी से इंटरफ़ेस लागू करना चाहिए, लेकिन extends कीवर्ड को उप-वर्ग में बहुत ही कम उपयोग करना चाहिए। वह अन्य चीजों के साथ इंगित करता है, जिसे fragile base-class समस्या के रूप में जाना जाता है। विकिपीडिया से:

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

2

"एक इंटरफ़ेस पर प्रोग्राम" अधिक लचीला हो सकता है।

उदाहरण के लिए, हम एक क्लास प्रिंटर लिख रहे हैं जो प्रिंट सेवा प्रदान करता है। वर्तमान में 2 वर्ग (Cat और Dog) मुद्रित होने की आवश्यकता है। इसलिए हम लिखने की तरह नीचे

class Printer 
{ 
    public void PrintCat(Cat cat) 
    { 
     ... 
    } 

    public void PrintDog(Dog dog) 
    { 
     ... 
    } 
    ... 
} 

कैसे अगर वहाँ एक नया वर्ग Bird है के बारे में भी इस प्रिंट सेवा की जरूरत कोड? हमें एक नई विधि प्रिंटबर्ड() जोड़ने के लिए Printer कक्षा को बदलना होगा। वास्तविक मामले में, जब हम प्रिंटर वर्ग विकसित करते हैं, तो हमें इस बारे में कोई जानकारी नहीं होगी कि इसका उपयोग कौन करेगा। तो Printer कैसे लिखना है? एक अंतरफलक मदद कर सकते हैं करने के लिए कार्यक्रम, कोड

class Printer 
{ 
    public void Print(Printable p) 
    { 
     Bitmap bitmap = p.GetBitmap(); 

     // print bitmap ... 
    } 
} 

इस नए प्रिंटर के साथ नीचे देखें, सब कुछ जब तक यह इंटरफ़ेस Printable लागू करता है मुद्रित किया जा सकता। यहां विधि GetBitmap() बस एक उदाहरण है। मुख्य बात यह है कि इंटरफ़ेस को कार्यान्वित नहीं करना है।

आशा है कि यह सहायक होगा।

+0

मैं इस जवाब को भी समझ नहीं सकता ... इसका क्या मतलब है? और क्या आप गंभीरता से कह रहे हैं कि कोड लिखना ठीक है जो संभावित रिफैक्टरिंग के 100 अंक उजागर करता है जब आप (काफी आसानी से) केवल एक को उजागर कर सकते हैं? –

+0

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

0

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

नोट, कि एक इंटरफ़ेस के रूप में एक सार वर्ग का उपयोग किया जा सकता है।

enter image description here

कार्यान्वयन पर आधारित प्रोग्रामिंग:

Motorcycle motorcycle = new Motorcycle(); 
motorcycle.driveMoto(); 

इंटरफेस पर आधारित प्रोग्रामिंग:

Vehicle vehicle; 
vehicle = new Motorcycle(); // Note that DI -framework can do it for you 
vehicle.drive(); 
0

यह मूल रूप से है जहां इस तरह की एक विधि/इंटरफ़ेस बनाने: create('apple') जहां विधि create(param) एक अमूर्त वर्ग/इंटरफ़ेस fruit से आता है जो बाद में im है कंक्रीट वर्गों द्वारा plemented। यह subclassing से अलग है। आप एक अनुबंध बना रहे हैं कि कक्षाएं पूरी करनी होंगी। यह युग्मन को कम करता है और चीजों को और अधिक लचीला बनाता है जहां प्रत्येक ठोस वर्ग इसे अलग-अलग लागू करता है।

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

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

संबंधित मुद्दे