क्या प्रथम श्रेणी के कार्य रणनीति पैटर्न का विकल्प हैं?


15

रणनीति डिजाइन पैटर्न अक्सर भाषाओं कि उन्हें कमी में प्रथम श्रेणी के कार्यों के लिए एक विकल्प के रूप में माना जाता है।

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

हालाँकि मैं इसके बारे में सोच रहा था और यह तय किया कि शायद रणनीति एक सादे अनाम फ़ंक्शन से अधिक प्रदान करता है।

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

ऑब्जेक्ट-ओरिएंटेड भाषा में जो प्रथम श्रेणी के कार्यों का समर्थन करता है, क्या रणनीति पैटर्न का फ़ंक्शंस का उपयोग करने पर कोई लाभ होता है?


10
"हालांकि, एक अनाम फ़ंक्शन अपने आप में केवल उस स्थिति को पकड़ सकता है जो फ़ंक्शन को पूरा करने के क्षण को समाप्त कर देता है।": यह सच नहीं है: एक क्लोजर राज्य को अलग-अलग आक्रमणों में रहता है।
जियोर्जियो

"हालांकि, एक अनाम फ़ंक्शन अपने आप में केवल उस स्थिति को पकड़ सकता है जो फ़ंक्शन के निष्पादन को समाप्त करने के क्षण को बंद कर देता है।" : वैश्विक चर, और स्थिर चर को कम से कम नहीं भूलना।
gbjbaanb

जवाबों:


13

जब भाषा फ़ंक्शन के संदर्भ का समर्थन करती है ( जावा 8 संस्करण के बाद से करता है ), ये अक्सर रणनीतियों के लिए एक अच्छा विकल्प होते हैं, क्योंकि वे आमतौर पर कम वाक्य रचना के साथ एक ही बात व्यक्त करते हैं। हालांकि, कुछ मामले हैं जहां एक वास्तविक वस्तु उपयोगी हो सकती है।

एक रणनीति इंटरफ़ेस में कई तरीके हो सकते हैं। आइए एक RouteFindingStragegyउदाहरण के रूप में इंटरफ़ेस लेते हैं , जो एल्गोरिदम को खोजने के विभिन्न मार्ग को एन्क्रिप्ट करता है। यह जैसे तरीकों की घोषणा कर सकता है

  • Route findShortestRoute(Node start, Node destination)
  • boolean doesRouteExist(Node start, Node destination)
  • Route[] findAllPossibleRoutes(Node start, Node destination)
  • Route findShortestRouteToClosestDestination(Node start, Node[] destinations)
  • Route findTravelingSalesmanRoute(Node[] stations)

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

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


2
"जब यह आंतरिक स्थिति बहुत जटिल हो जाती है, तो यह अक्सर पूर्ण वर्ग के लिए बंद को बढ़ावा देने के लिए उपयोगी हो जाता है": क्यों? यदि आंतरिक स्थिति जटिल हो जाती है, तो आप इसे एक ऑब्जेक्ट / रिकॉर्ड में भी रख सकते हैं जो क्लोजर के अंदर संग्रहीत होता है।
जियोर्जियो

1
@ जियोर्जियो लेकिन फिर आपके पास दो सिंटेक्स इकाइयाँ होंगी - जो कि अपनी आंतरिक स्थिति का प्रबंधन करती है। इसलिए कोड को उस कक्षा में बंद करके सरल बनाया जा सकता था। यह बेहतर हो सकता है या यह नहीं हो सकता है, जो सटीक उपयोग-मामले, प्रोग्रामिंग भाषा और व्यक्तिगत प्राथमिकता पर निर्भर करता है।
फिलिप

यह मेरे लिए एक उचित विचार है।
जियोर्जियो

5

यह सच नहीं है कि एक अनाम फ़ंक्शन केवल उस स्थिति को पकड़ सकता है जो फ़ंक्शन के निष्पादन को समाप्त करने के लिए मौजूद है।

आम लिस्प में निम्नलिखित उदाहरण लें:

(defun number-strings (ss)
  (let ((counter 0))
    (mapcar #'(lambda (s) (format nil "~a: ~a" (incf counter) s)) ss)))

यह फ़ंक्शन स्ट्रिंग्स की एक सूची लेता है और सूची के प्रत्येक तत्व के लिए एक काउंटर तैयार करता है। इसलिए, उदाहरण के लिए, आह्वान

(number-strings '("a" "b" "c"))

देता है

("1: a" "2: b" "3: c")

फ़ंक्शन number-stringsआंतरिक रूप से एक चर के साथ एक अनाम फ़ंक्शन का उपयोग करता हैcounter राज्य (काउंटर का वर्तमान मूल्य) रखता है जिसे फ़ंक्शन द्वारा आह्वान किए जाने पर हर बार पुन: उपयोग किया जाता है।

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

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


तो एक भाषा में जो फर्स्ट क्लास फ़ंक्शंस को बंद करने का समर्थन करता है, क्या आप कभी भी 'क्लासिक' रणनीति का उपयोग करेंगे?
अवीव कोहन

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

1

सिर्फ इसलिए कि दो डिजाइन एक ही समस्या को हल कर सकते हैं इसका मतलब यह नहीं है कि वे एक दूसरे के लिए प्रत्यक्ष प्रतिस्थापन हैं।

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

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


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

क्षमा करें, लेकिन मैं आपके तर्क का पालन नहीं कर सकता। विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग में राज्य से निपटने के लिए हाथ में सवाल के साथ क्या करना है?
फिलिप

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

1

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

अवधि की रणनीति ज्यादातर अन्य प्रोग्रामर के साथ बातचीत संक्षेप में अपने इरादे को व्यक्त करने में उपयोगी है। इसके बारे में कुछ भी जादुई नहीं है।


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

मैं @Snowman से सहमत हूँ। क्या आप सुनिश्चित हैं कि आप रणनीति पैटर्न के बारे में बात कर रहे हैं ?
रोवन फ्रीमैन

1
@Snowman, यहां तक ​​कि आप जिस पेज से जुड़े हैं, वह यह नहीं बताता है कि इस पैटर्न को कैसे लागू किया जाना चाहिए, बल्कि वे विशिष्ट भाषाओं में उदाहरण देते हैं, लेकिन यूएमएल आरेख में ऐसा कुछ भी नहीं है जो कहता है कि मुझे सी ++ विरासत, जावा इंटरफेस या रूब ब्लॉक का उपयोग करने की आवश्यकता है । इसलिए मैं आपके विश्लेषण से असहमत हूं।
आलसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.