2009-12-17 17 views
6

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

Private Function WidgetFactory(typeId) 
    Dim oWidget 
    Select Case typeId 
     Case widgetType.ContentBlock 
      Set oWidget = New ContentWidget 
     Case widgetType.Registration 
      Set oWidget = New RegistrationWidget 
     Case widgetType.DocumentList 
      Set oWidget = New DocumentListWidget 
     Case widgetType.DocumentDisplay 
    End Select 
    Set WidgetFactory = oWidget 
End Function 

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

तो, क्या मैं इसे गलत कर रहा हूं? क्या इस परिदृश्य को संभालने का कोई बेहतर तरीका है?

उत्तर

15

मुझे लगता है कि आपको खुद से पूछना चाहिए प्रश्न: मैं यहां फैक्टरी विधि का उपयोग क्यों कर रहा हूं?

अगर जवाब "एक की वजह से ", और एक एक अच्छा कारण है, तो यह करना जारी रखने, भले ही वह कुछ अतिरिक्त कोड का मतलब है। अगर उत्तर "है तो मुझे नहीं पता, क्योंकि मैंने सुना है कि आपको ऐसा करने की ज़रूरत है?" तो आपको पुनर्विचार करना चाहिए।

कारखानों का उपयोग करने के मानक कारणों पर चलो चलें। यहाँ फैक्टरी विधि पैटर्न के बारे में क्या Wikipedia says है:

[...], यह है कि बनाया जाएगा वस्तु की सही वर्ग निर्दिष्ट किए बिना वस्तुओं (उत्पाद) बनाने की समस्या से संबंधित है। फ़ैक्टरी विधि डिज़ाइन पैटर्न ऑब्जेक्ट्स बनाने के लिए एक अलग विधि को परिभाषित करके इस समस्या को संभालता है, जिसका उप-वर्ग तब व्युत्पन्न प्रकार के उत्पाद को निर्दिष्ट करने के लिए ओवरराइड कर सकता है।

के बाद से अपने WidgetFactoryPrivate है, यह स्पष्ट रूप से कारण है कि आप इस पैटर्न का उपयोग नहीं है। "कारखाना पैटर्न" के बारे में क्या (स्वतंत्र है कि आप इसे फैक्टरी विधि या अमूर्त वर्ग का उपयोग करके कार्यान्वित करते हैं)? फिर, Wikipedia says:

उपयोग कारखाना पैटर्न जब:

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

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


संपादित करें: मुझे इस सामान्य विस्तार के बाद वापस अपने विशेष मामले के लिए प्राप्त करते हैं: आमतौर पर, यह a = new XyzWidget() बनाम a = WidgetFactory.Create(WidgetType.Xyz) है। हालांकि, आपके मामले में, आपके पास डेटाबेस से कुछ (संख्यात्मक?) typeId है। जैसा कि मार्क सही ढंग से लिखा गया है, आपको typeId -> className मानचित्र कहीं होना चाहिए।

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

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

+0

+1 सटीक और बिंदु पर। –

+0

आपके उत्तर के लिए धन्यवाद। मुझे लगता है कि पहले सवाल का जवाब "मुझे नहीं पता ..." हो सकता है। मेरी विधि के लिए वैकल्पिक दृष्टिकोण क्या हो सकता है? मुझे डेटाबेस में टाइप आईडी के किस मूल्य के आधार पर विजेट का एक अलग उप-वर्ग बनाना होगा। – jammus

+0

@jammus: मैंने अपना जवाब संपादित किया। – Heinzi

0

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

4

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

Refactoring में एक बहुत अच्छा स्पष्टीकरण है कि क्यों स्विच/चयन केस स्टेटमेंट कोड गंध हैं, लेकिन यह मुख्य रूप से उस मामले को संबोधित करता है जहां आपके पास कई समान स्विच हैं।

यदि आपकी विजेट फैक्टरी विधि केवल है जहां आप उस विशेष enum पर स्विच करते हैं, तो मैं कहूंगा कि आपको चिंता करने की ज़रूरत नहीं है। आपको उस मानचित्र को कहीं और रखना होगा।

एक विकल्प के रूप में, आप मानचित्र को एक शब्दकोश के रूप में परिभाषित कर सकते हैं, लेकिन कोड लाइनों की मात्रा में काफी कमी नहीं आएगी - आप आधे में कोड की रेखाओं को काट सकते हैं, लेकिन जटिलता की डिग्री बराबर रहेगी ।

2

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

2

चाहे यह उचित है या नहीं, मैंने हमेशा विश्वास किया है कि फैक्ट्री का उपयोग करने का समय तब होता है जब वस्तु का निर्माण करने का निर्णय उस समय पर आधारित होगा जो रन-टाइम तक उपलब्ध नहीं है।

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

4

फैक्टरी पैटर्न का आपका आवेदन सही है। आपके पास ऐसी जानकारी है जो निर्देशित करती है कि किस प्रकार के एन प्रकार बनाए गए हैं। एक कारखाना जानता है कि यह कैसे करना है। (यह एक निजी विधि के रूप में थोड़ा अजीब है। मुझे उम्मीद है कि यह IWidgetFactory इंटरफ़ेस पर होगा।)

आपका कार्यान्वयन कंक्रीट प्रकारों के कार्यान्वयन को कसकर जोड़ता है। यदि आपने typeId -> widgetType मैप किया है, तो आप फैक्टरी को किसी विजेट प्रकार को समझने के लिए Activator.CreateInstance(widgetType) का उपयोग कर सकते हैं।

अब, आप मैपिंग को परिभाषित कर सकते हैं, हालांकि आप चाहते हैं: कॉन्फ़िगरेशन फ़ाइल में एक साधारण शब्दकोश, खोज (विशेषता/प्रतिबिंब) आदि। आपको कहीं भी एक ही स्थान पर सभी प्रकारों को जानना होगा, लेकिन आपके पास भी एकाधिक स्रोतों को लिखने का विकल्प।

+0

+1 इस बात से सहमत है कि यहां क्या हो रहा है इसका मूल मैपिंग है, क्योंकि स्विच में इसे रखने वाला पहला कदम चीजों को एक साथ रखता है, फिर इसे एक अच्छा परिष्करण के साथ अतिरिक्त कॉन्फ़िगरेशन, प्रतिबिंब आदि के साथ अधिक आसानी से एक्स्टेंसिबल बना देता है। – djna

1

यह मेरा अनुभव रहा है कि फैक्ट्री बढ़ती हैं इसलिए उनकी निर्भरताओं को नहीं करना पड़ता है। यदि आप यह मानचित्रण अन्य स्थानों पर डुप्लिकेट करते हुए देखते हैं तो आपके पास चिंता का कारण है।