क्या Iterator एक डिजाइन पैटर्न बनाता है?


9

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

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

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

हम शायद लेखक, पेंटर, एनकोडर, और शायद बेहतर वाले जैसे कई और समान उदाहरण पा सकते हैं, जो उसी तरह काम करते हैं। हालाँकि मैंने इनमें से किसी को भी डिज़ाइन पैटर्न कहा जा रहा है।

तो क्या Iterator खास बनाता है?

क्या यह तथ्य है कि यह अधिक जटिल है क्योंकि इसे संग्रह के भीतर वर्तमान स्थिति को संग्रहीत करने के लिए परस्पर अवस्था की आवश्यकता होती है? लेकिन फिर, उत्परिवर्तनीय स्थिति को आमतौर पर वांछनीय नहीं माना जाता है।


अपनी बात स्पष्ट करने के लिए, मुझे एक और विस्तृत उदाहरण देना चाहिए।

यहाँ हमारे डिजाइन समस्या है:

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

हमारी डिजाइन समस्या के लिए एक समझदार समाधान (व्यावहारिक रूप से पुनरावृत्त पैटर्न का सामान्यीकरण):

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

एक उदाहरण:

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

MathObject i = new MyInteger(5);
Power powerOfFive = i.getPower();
MyInteger square = powerOfFive.calculate(2); // should return 25
MyInteger cube = powerOfFive.calculate(3); // should return 125

5
"वर्ग आरेख समान होगा" - तो क्या? एक डिजाइन पैटर्न एक वर्ग आरेख नहीं है। यह आवर्ती समस्या के समाधान के एक वर्ग के लिए एक उच्च स्तरीय अमूर्तता है।
डॉक्टर ब्राउन

@DocBrown: ठीक है, लेकिन गणितीय कार्य नहीं हैं, किसी फ़ाइल में ऑब्जेक्ट्स लिखना, ग्राफ़िकल आउटपुट या एन्कोडिंग डेटा पुनरावृत्ति समस्याएँ, जैसे पुनरावृत्ति?
फ्रैंक पफर

डिज़ाइन पैटर्न की पसंद व्यक्तिपरक है (यानी "डिजाइनरों" की नज़र में, या वे लोग जो डिज़ाइन को जज करते हैं)। डिज़ाइन पैटर्न के नामकरण का उद्देश्य डोमेन-अज्ञेयवादी होना है (ताकि हम यह सोचकर विचलित न हों कि यह डोमेन-विशिष्ट है)। बस मेरी राय, मेरे पास कोई हवाला नहीं है।
रवांग

@FrankPuffer यदि आप किसी फ़ाइल में ऑब्जेक्ट लिखने के लिए एक सामान्य समाधान को रेखांकित करते हैं, तो आप अपना समाधान लिख सकते हैं और ऐसा करने में ऑब्जेक्ट राइटिंग पैटर्न को कॉल कर सकते हैं।
ब्रैंडिन

3
आप इसे खत्म कर रहे हैं। एक डिजाइन पैटर्न एक सामान्य कंप्यूटिंग समस्या का एक प्रसिद्ध समाधान है, और यह सब है। आप पैटर्न का उपयोग तब करते हैं जब आप इसे प्रदान करने वाले लाभों को पहचान सकते हैं और लागू कर सकते हैं।
रॉबर्ट हार्वे

जवाबों:


9

GoF पुस्तक के अधिकांश पैटर्न में निम्नलिखित बातें समान हैं:

  • वे ऑब्जेक्ट-ओरिएंटेड साधनों का उपयोग करके मूल डिज़ाइन समस्याओं को हल करते हैं
  • लोग अक्सर मनमाने ढंग से कार्यक्रमों में इस तरह की समस्याओं का सामना करते हैं, डोमेन या व्यवसाय से अनिच्छापूर्वक
  • वे कोड को अधिक पुन: प्रयोज्य बनाने के लिए व्यंजनों हैं, अक्सर इसे और अधिक ठोस बनाकर
  • वे इन समस्याओं के लिए कैनोनिक समाधान प्रस्तुत करते हैं

इन पैटर्नों द्वारा हल की गई समस्याएं इतनी बुनियादी हैं कि कई डेवलपर्स उन्हें मुख्य रूप से लापता प्रोग्रामिंग भाषा सुविधाओं के लिए वर्कअराउंड के रूप में समझते हैं , जो IMHO देखने का एक वैध बिंदु है (ध्यान दें कि GoF पुस्तक 1995 से है, जहां जावा और C ++ ने इतनी पेशकश नहीं की थी आज जैसी सुविधाएँ)।

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

अब इसे अपनी चुनी हुई समस्याओं से तुलना करें:

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

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


The problems solved by these patterns are so basic that many developers think their main purpose is to be workarounds for missing programming language features- विडंबना यह है कि सॉफ़्टवेयर डेवलपर नियमित रूप से सॉफ़्टवेयर डिज़ाइन पैटर्न का उपयोग करते हैं जो 20 साल पुराने हैं, जबकि अभी भी विश्वास है कि वे अत्याधुनिक कोड लिख रहे हैं।
रॉबर्ट हार्वे

@ रोबर्टहाइवे: मुझे नहीं लगता कि कई देवता गोफ द्वारा सुझाए गए "ऊ मार्ग" में आज पुनरावृत्त पैटर्न को लागू करेंगे। वे इसे आमतौर पर भाषा द्वारा प्रदान किए गए माध्यमों से लागू करते हैं या यह मानक रूप से उपयुक्त है (उदाहरण के लिए, C # का उपयोग करके IEnumerableऔर yield)। लेकिन अन्य GoF पैटर्न के लिए, आपने जो लिखा है वह शायद सच हो सकता है।
डॉक ब्राउन

1
workarounds for missing programming language features: Blog.plover.com/prog/johnson.html पर
jrw32982

8

द गैंग ऑफ़ फोर कोटे क्रिस्टोफर अलेक्जेंडर की पैटर्न परिभाषा:

प्रत्येक पैटर्न एक समस्या का वर्णन करता है जो हमारे पर्यावरण में बार-बार होता है, और फिर उस समस्या के समाधान का मूल वर्णन करता है […]

पुनरावृत्तियों द्वारा हल की गई समस्या क्या है?

आशय: किसी कुल वस्तु के तत्वों को उसके अंतर्निहित प्रतिनिधित्व को उजागर किए बिना क्रमिक रूप से उपयोग करने का एक तरीका प्रदान करें।

...

प्रयोज्यता: Iterator पैटर्न का उपयोग करें

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

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

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

while (my ($key, $value) = each %$hash) {
  say "$key => $value";
}

लेकिन क्या होगा अगर हम लूप बॉडी में एक फ़ंक्शन कहते हैं?

while (my ($key, $value) = each %$hash) {
  do_something_with($key, $value, $hash);
}

यह फ़ंक्शन अब बहुत कुछ कर सकता है, जो भी इसे छोड़कर, चाहता है:

  • हैश प्रविष्टियों को जोड़ें या हटाएं, क्योंकि ये पुनरावृत्ति क्रम को अप्रत्याशित रूप से बदल देंगे (C ++ में - बोलें, ये पुनरावृत्ति को अमान्य कर देंगे)।
  • एक ही हैश तालिका को कॉपी किए बिना पुनरावृति करें, क्योंकि यह उसी पुनरावृत्ति स्थिति का उपभोग करेगा। उफ़।

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

हां, निश्चित रूप से पुनरावृत्त पैटर्न अन्य पैटर्न से संबंधित है। उदाहरण के लिए, पुनरावृत्त कैसे त्वरित किया जाता है? जावा में, हमारे पास एक सामान्य Iterable<T>और Iterator<T>इंटरफ़ेस है। एक ठोस पुनरावृत्ति की तरह ArrayList<T>एक विशेष प्रकार के पुनरावृत्त बनाता है, जबकि HashSet<T>एक पूरी तरह से अलग प्रकार का आपूर्ति कर सकता है। यह मुझे अमूर्त कारखाने पैटर्न की बहुत याद दिलाता है, जहां Iterable<T>सार कारखाना है और Iteratorउत्पाद है।

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

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

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


NIce जवाब, धन्यवाद। अभी भी पूरी तरह से आश्वस्त नहीं हैं कि अंतिम पैराग्राफ में आप जो लिखते हैं वह यहां लागू होता है। मैंने अपने प्रश्न को यह समझाने के लिए संपादित किया है कि मेरा क्या मतलब है।
फ्रैंक पफर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.