2008-11-20 4 views
8

ठीक तो मैं एक कुछ कोड है जो इस तरह मोटे तौर पर लग रहा है देख रहा हूँ:एक डिजाइन पैटर्न के लिए खोज रहे huuuge को बदलने के लिए करता है, तो पर वस्तु प्रकार

void DoSomething(object o) 
{ 
    if (o is Sometype1) { 
    //cast o to Sometype and do something to it 
    } 
    else if (o is Sometype2) { 
    //cast o to Sometype2 and do something to it 
    } 
    ... 
    else if (o is SometypeN) { 
    //cast o to SometypeN and do something to it 
    } 
} 

अब एक दृष्टिकोण सभी वस्तुओं o हैं कि बनाने के लिए किया जाएगा कुछ विधि करने के वास्तव में उन लोगों के साथ संबंधित नहीं है के लिए तर्क - मानकों की तरह

interface ICanHaveSomethingDoneToMe 
{ 
    //expose various properties that the DoSomething method wants to access 
} 

एक इंटरफ़ेस को लागू के रूप में लेकिन इस के साथ समस्या यह है कि मैं अपने सभी वस्तुओं को इस इंटरफ़ेस को लागू नहीं करना चाहती है इस्तेमाल किया। इस से निपटने के लिए मुझे किस पैटर्न का उपयोग करना चाहिए?

मैं

interface IPropertiesForDoingSomethingTo<T> 
{ 
    //expose various properties that the DoSomething method wants to access 
} 

के कार्यान्वयन की एक श्रृंखला की तरह कुछ संदेह है बेहतर हो सकता है। मेरे पास प्रत्येक ऑब्जेक्ट प्रकार के लिए एक कार्यान्वयन होगा जिसे मैं करना चाहता हूं, लेकिन फिर मुझे यह नई समस्या है। मुझे बिंदु पर

IPropertiesForDoingSomethingTo<T> GetPropsGeneric(T t); 

पर एक विधि की आवश्यकता होगी, लेकिन क्या इस पर भारी स्विच करने की आवश्यकता होगी? मैं की तरह

IPropertiesForDoingSomethingTo<Someobject1> GetProps(Someobject1 t); 
... 
IPropertiesForDoingSomethingTo<Someobject1> GetProps(SomeobjectN t); 

तरीकों का भार के साथ एक वर्ग को परिभाषित करना चाहिए यह जेनेरिक वर्जन है कि आप क्रम में नए प्रकार जोड़ने के लिए सक्षम नहीं होगा की तुलना में समस्या है। Ts वहाँ कंटेनर को हल करने के लिए GetPropsGeneric में एक डी कंटेनर के साथ कुछ चालाक कर सकते हैं? धन्यवाद!

उत्तर

6

किसी भी समय जब आप किसी ऑब्जेक्ट के प्रकार की जांच कर रहे स्विच कथन (या if-statement की एक श्रृंखला) देखते हैं, तो यह एक लापता बेस क्लास या इंटरफ़ेस के लिए एक बड़ा लाल झंडा है। दूसरे शब्दों में, कोड पॉलीमोर्फिज्म पर निर्भर होना चाहिए, ऑब्जेक्ट प्रकार

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

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

+1

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

+0

पैरामीटर की जांच करने के लिए यदि आपके पास कोई कथन/स्विच है तो एक वस्तु बनाएं यानी फैक्टरी पैटर्न – Julio

+0

@ फ्रैंको ऑफहैंड, मैं कहूंगा कि आप फैक्ट्री पैटर्न को गलत व्याख्या कर रहे थे; http://en.wikipedia.org/wiki/Factory_method_pattern देखें –

2

ऐसा लगता है कि आप C# का उपयोग कर रहे हैं। मेरा मानना ​​है कि आप "एक्सटेंशन विधियां" बना सकते हैं जो पहले से स्थापित कक्षाओं से जुड़ी हैं।

एक और तरीका ऑब्जेक्ट प्रकार द्वारा की गई हैशटेबल में प्रतिनिधियों को प्रत्येक प्रकार और स्टोर संदर्भों के लिए हैंडलर प्रतिनिधियों को बनाना होगा।

फिर आपकी "DoSomething" विधि केवल पारित ऑब्जेक्ट के प्रकार द्वारा निष्पादित प्रतिनिधि को देख सकती है और निष्पादित कर सकती है।

0

एक वास्तविक उदाहरण अधिक उपयोगी होगा। यदि आप बस संबंधित वर्गों के परिवार के लिए एक विधि के कार्यान्वयन को बदल रहे हैं, तो @ स्टेवेन ए लोवे कहते हैं, आप पॉलिमॉर्फिज्म का उपयोग करके और इसके लिए उप-वर्ग संबंधों का उपयोग करके सबसे अच्छे हैं। यदि कक्षाएं "एक" संबंधों में भाग नहीं लेती हैं, तो Visitor जैसे अन्य पैटर्न अधिक उपयुक्त हो सकते हैं।

0

पॉलिमॉर्फिज्म उत्तर है, जहां मूल वस्तु पारित की जाती है। हालांकि, यह संभवतया आप जितना चाहें बॉयलरप्लेट और अर्थात् जटिलता है।

इसे आपकी कार्यक्षमता को किसी भी तरह व्युत्पन्न कक्षाओं में और किसी "वर्चुअल" फ़ंक्शन को लागू करने की आवश्यकता होगी।

0

मुझे लगता है कि यह एक आस्पेक्ट ओरिएंटेड प्रोग्रामिंग दृष्टिकोण के लिए एक प्रश्न है।

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

अनिवार्य रूप से, इस तरह से सोचें; आप एक इंटरफ़ेस अनुबंध को परिभाषित कर रहे हैं जिसे आप पैरामीटर ऑब्जेक्ट्स को कार्यान्वित करना चाहते हैं ; और अपनी वस्तु के उप-वर्गों के रूप में "सजावट" को परिभाषित करना और इंटरफ़ेस जो आपके विशिष्ट वर्ग के लिए इंटरफ़ेस व्यवहार (इसलिए अनुबंध को पूरा करना) के विशिष्ट कार्यान्वयन को लागू करता है। इस तरह, आप इसके लिए DoSomething विधि का कार्यान्वयन कर सकते हैं प्रत्येक वर्ग पूरी तरह से उन वर्गों के स्रोत से अलग है रों।

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

स्प्रिंग एओपी इस सामान के बारे में बहुत अच्छा है। मैं इसे पढ़ूंगा।

0

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

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