डेकोरेटर डिजाइन पैटर्न के बारे में नौसिखिया सवाल


18

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

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

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

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

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

लेख में एक और पंक्ति थी:

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

मुझे नहीं मिलता कि वे कहाँ कहते हैं "... परिवर्तन मूल वर्ग के सभी उदाहरणों को प्रभावित करता है" - उपवर्ग कैसे मूल वर्ग को बदलता है? उपवर्ग के पूरे बिंदु नहीं है?

मैं यह मानकर चल रहा हूं कि कई विकी की तरह लेख भी स्पष्ट रूप से नहीं लिखा गया है। मैं उस अंतिम पंक्ति में डेकोरेटर की उपयोगिता देख सकता हूं - "... व्यक्तिगत वस्तुओं के लिए रन-टाइम पर नया व्यवहार प्रदान करता हूं"।

इस पैटर्न के बारे में पढ़े बिना, अगर मुझे अलग-अलग वस्तुओं के लिए रन-टाइम में व्यवहार को बदलने की आवश्यकता होती है, तो मैंने संभवतः व्यवहार को सक्षम / अक्षम करने के लिए सुपर या उपवर्ग में कुछ तरीकों का निर्माण किया होगा। कृपया मुझे वास्तव में डेकोरेटर की उपयोगिता को समझने में मदद करें, और मेरी नौसिखिया सोच क्यों दोषपूर्ण है?


एडिटर्स, वाल्टर ... फी की सराहना करते हैं, मैंने "लोगों" का इस्तेमाल महिलाओं को बाहर करने के लिए नहीं, बल्कि एक अनौपचारिक ग्रीटिंग के रूप में किया।
जिम

संपादन सामान्य रूप से ग्रीटिंग को हटाने के लिए होगा। यह मानक एसओ / एसई प्रोटोकॉल सवालों में एक का उपयोग करने के लिए नहीं है [चिंता न करें, हमें नहीं लगता कि यह सीधे सवाल में कूदने के लिए अशिष्ट है]
Farrell

धन्यवाद! यह सिर्फ इतना था कि उसने इसे "लिंग को हटाने" को टैग किया था और मुझे यह सोचने के लिए किसी से नफरत होगी कि मैं गलत या कुछ और हूं !! :)
जिम

मैं उन्हें इस्तेमाल भारी उन कानूनी प्रक्रियात्मक बातें "सेवाओं" कहा जाता है से बचने के लिए: medium.com/@wrong.about/...
Zapadlo

जवाबों:


13

डेकोरेटर पैटर्न वह है जो विरासत पर रचना का पक्ष लेता है [एक और OOP प्रतिमान जिसके बारे में जानने के लिए उपयोगी है]

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

डेकोरेटर के साथ, आप बस एक नया वर्ग जोड़ते हैं जो इस व्यवहार का वर्णन करता है, और वह यह है - पैटर्न आपको प्रभावी रूप से बिना किसी संशोधन के बाकी कोड में इसे छोड़ने की अनुमति देता है।
उप-वर्गीकरण के साथ, आपको अपने हाथों पर एक बुरा सपना मिला है।
एक सवाल जो आपने पूछा था, "उपवर्ग अभिभावक वर्ग को कैसे बदलता है?" ऐसा नहीं है कि यह मूल वर्ग को बदलता है; जब यह एक उदाहरण कहता है, तो इसका मतलब है कि आपने 'तात्कालिक' [यदि आप जावा या सी # का उपयोग कर रहे हैं, उदाहरण के लिए, newकमांड का उपयोग करके ]। जब आप इन बदलावों को एक वर्ग में जोड़ते हैं, तो यह आपके लिए उस परिवर्तन के लिए कोई विकल्प नहीं है, भले ही आपको वास्तव में इसकी आवश्यकता न हो।

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

एक दिलचस्प बिंदु जो बनाया जाना चाहिए: आप एक ही कार्यक्षमता को कई बार जोड़ सकते हैं; उदाहरण के लिए, उदाहरण के लिए, आपके पास डबल, ट्रिपल या जो भी राशि या सीमा है, उसकी आवश्यकता के अनुसार एक खिड़की हो सकती है।

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


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

इसके अलावा, सील वर्गों के बारे में हिस्सा समझदारी का टन बनाता है ... धन्यवाद!
जिम

3

उपवर्ग के साथ स्क्रॉलबार और सीमाएं जोड़ने की संभावनाओं पर विचार करें। यदि आप हर संभावना चाहते हैं, तो आपको चार कक्षाएं मिलेंगी (पायथन):

class Window(object):
    def draw(self):
        "do actual drawing of window"

class WindowWithScrollBar(Window):
    def draw(self):
        Window.draw(self)
        "do actual drawing of scrollbar"

class WindowWithBorder(Window):
    def draw(self):
        Window.draw(self)
        "do actual drawing of border"

class WindowWithScrollBarAndBorder(Window):
    def draw(self):
        WindowWithScrollBar.draw(self)
        WindowWithBorder.draw(self)

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

class Window(object):
    ...

class WindowWithGimmick(Window):
    ...

class WindowWithScrollBar(Window):
    ...

class WindowWithBorder(Window):
    ...

class WindowWithScrollBarAndBorder(Window):
    ...

class WindowWithScrollBarAndGimmick(Window):
    ...

class WindowWithBorderAndGimmick(Window):
    ...

class WindowWithScrollBarAndBorderAndGimmick(Window):
    ...

इसका मतलब है कि पारस्परिक रूप से स्वतंत्र सुविधाओं के एक सेट के लिए f | f | f | सुविधाओं की संख्या होने के नाते, आपको 2 ** को परिभाषित करना होगा | f | कक्षाएं, जैसे। यदि आपके पास 10 सुविधाएँ हैं, तो आपको 1024 कसकर युग्मित कक्षाएं मिलती हैं। यदि आप डेकोरेटर पैटर्न का उपयोग करते हैं, तो हर सुविधा का अपना स्वतंत्र और शिथिल युग्मित वर्ग है और आपके पास केवल 1 + + f है। कक्षाएं (जो ऊपर दिए गए उदाहरण के लिए 11 हैं)।


देखिए, मेरी सोच वर्गों को जोड़ते रहना नहीं होगा - यह मूल (उप) वर्ग में फ़ंक्शनलिटी को जोड़ना होगा। इसलिए क्लास विंडो (ऑब्जेक्ट) में: आपके पास स्क्रॉलबार = ट्रू, बॉर्डर = गलत, आदि ... उत्तर Farrell मुझे दिखाता है कि कहां गलत हो सकता है, हालांकि - बस फूला हुआ वर्गों के लिए अग्रणी और इस तरह ... उत्तर के लिए धन्यवाद, +1!
जिम

ठीक है, +1 एक बार मेरे पास ऐसा करने के लिए प्रतिनिधि है!
जिम

2

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

आपके द्वारा उल्लिखित उदाहरण वास्तव में यहाँ बहुत करीने से कवर किया गया है:

किसी वस्तु की कार्यक्षमता का विस्तार करना वंशानुक्रम का उपयोग करके (संकलित समय पर) किया जा सकता है, हालांकि किसी वस्तु की कार्यक्षमता को गतिशील रूप से (रनटाइम पर) वस्तु के रूप में उपयोग करना आवश्यक हो सकता है।

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

http://www.oodesign.com/decorator-pattern.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.