2010-05-08 14 views
5

यह एक डिज़ाइन प्रश्न है ... यदि आपयदि आप उस वर्ग से उत्तराधिकारी नहीं हो सकते हैं जिसे आप सजाने के लिए चाहते हैं तो आप सजावट पैटर्न को कैसे कार्यान्वित कर सकते हैं?

1) ऑब्जेक्ट को "मुहरबंद" चिह्नित किया गया है जिसका अर्थ है कि आप इससे विस्तार नहीं कर सकते हैं। 2) या आप एक विधि को ओवरराइड करना चाहते हैं लेकिन यह वर्चुअल नहीं है।

तब आप क्या कर सकते हैं? यदि आपके पास स्रोत कोड नहीं है (जैसे किसी तृतीय पक्ष लाइब्रेरी) में क्लास स्रोत कोड नहीं बदला जा सकता है।

उत्तर

1

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

1) आप तृतीय-पक्ष कोड को एक सीलबंद वर्ग का एक उदाहरण से गुजर रहे हैं:

+1

लेकिन आप विषय वर्ग को प्रॉक्सी कक्षा के साथ प्रतिस्थापित नहीं कर पाएंगे क्योंकि उनके पास विभिन्न प्रकार हैं। – Ikke

+0

@ikke: यह सच है। इसलिए मैंने प्रॉक्सी पैटर्न नहीं कहा। – Ikaso

+1

प्रॉक्सी के विपरीत एडाप्टर नहीं होगा? –

2

दृष्टिकोण आप कोड तुम सच है के ऊपर कितना नियंत्रण के आधार पर ले सकता है बहुत से? यदि हां, तो आप ऐसा नहीं कर सकते हैं, प्रार्थना करें कि आपकी तीसरी पार्टी एक ठोस वस्तु के बजाय एक इंटरफ़ेस स्वीकार करती है।

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

2) क्या आप अपने कोड में मुहरबंद कक्षा का उपभोग कर रहे हैं? यदि ऐसा है, तो गैजेट रैपर जाओ! अपनी सीलबंद कक्षा के समान सार्वजनिक तरीकों के साथ एक गैर-मुहरबंद कक्षा बनाएं, सार्वजनिक तरीकों को आपके मुहरबंद वस्तु से गुज़रना चाहिए, फिर आप अपनी कक्षा की कार्यक्षमता को आवश्यकतानुसार ओवरराइड कर सकते हैं।

3) क्या आपके पास सीलबंद कक्षा में कोड है? यदि ऐसा है, तो वर्ग परिभाषा पाएं, इसे हाइलाइट करने के लिए 'मुहरबंद' कीवर्ड को डबल-क्लिक करें, आवश्यकतानुसार हटाएं कुंजी दबाएं;) या हो सकता है कि वे विधियों को स्वैप करें जो आपके सीलबंद ऑब्जेक्ट को एक ही सार्वजनिक तरीकों के साथ इंटरफ़ेस के लिए स्वीकार करते हैं।

5

सजावट पैटर्न के लिए विरासत आवश्यक नहीं है। सबसे आसान मामला यह है कि यदि ऑब्जेक्ट आप सजाने के लिए एक इंटरफेस लागू करना चाहते हैं। फिर अपने डेकोरेटर बस एक ही इंटरफ़ेस को लागू कर सकते हैं:

[ IWindow ] 
[ + Draw() ] 
--------------- 
    | 
    +--- [ Window ] 
    | [ + Draw() ] 
    | 
    | 
    +--- [ DecoratedWindow ] 
     [ + Draw()  ] 
     ------------------- 
     | 
     +--- [ BorderDecorator ] 
     | 
     +--- [ VerticalScrollbarDecorator ] 
     | 
     +--- [ HorizontalScrollbarDecorator ] 

अब आप कर सकते हैं:

IWindow w = new BorderDecorator(
      new HorizontalScrollBarDecorator(
       new VerticalScrollBarDecorator(
       new Window(80, 24)))); 

// This is a window with a border and scrollbars, even though 
// the original Window class has no idea what those are. 
w.Draw(); 

क्या संभव हो रहे हैं की बारीकियों वर्ग आप की कोशिश कर रहे की सही प्रकृति पर निर्भर करेगा सजाने के लिए।

+0

इंटरफेस के खिलाफ डिजाइन के लिए +1। कक्षाएं विरासत में नहीं होने पर यह * विशेष रूप से * महत्वपूर्ण है! – Aaronaught

0

यदि आप वारिस नहीं कर सकते हैं और मूल श्रेणी किसी भी इंटरफेस को लागू नहीं करती है जिसे आप अपने सजावटी पर भी कार्यान्वित कर सकते हैं, तो मेरा मानना ​​है कि आपको प्रॉक्सी क्लास या एडाप्टर का प्रयास करना चाहिए। और यदि यह भी संभव नहीं है, तो, आपके पास हमेशा "वैकल्पिक तकनीकी संसाधन" होता है: आप conversion operator को अपने सजावटी को मूल में डालने की इजाजत दे सकते हैं (पूरी तरह से मेरा मानना ​​है कि यह एक बहुत अच्छा विकल्प नहीं है)।

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

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