2009-08-16 13 views
29

मेरे पास बहुत सारी (सार) कारखानियां हैं और उन्हें आम तौर पर सिंगलेट के रूप में लागू किया जाता है।"सिंगलटन" कारखानों, ठीक है या बुरा?

आमतौर पर उन परतों के माध्यम से उन्हें पारित करने की सुविधा के लिए, जिनके पास वास्तव में इन कारखानों का उपयोग करने या जानने के साथ कोई व्यवसाय नहीं है।

अधिकांश समय मैं केवल जो कारखाने कार्यान्वयन के कोड कार्यक्रम के बाकी है, शायद कुछ विन्यास

यह जैसे लग रहा है के माध्यम से स्टार्टअप पर एक निर्णय करने की जरूरत है यह हो सकता है और अधिक एक सिंगलटन की तुलना में एक disuised वैश्विक है - जैसे

abstract class ColumnCalculationFactory { 
    private static ColumnCalculationFactory factory; 

public static void SetFactory(ColumnCalculationFactory f) { 
     factory = f; 
    } 

    public static void Factory() { 
     return factory; 
    } 

public IPercentCalculation CreatePercentCalculation(); 
public IAverageCalculation CreateAverageCalculation(); 
    .... 

} 

someting इस बारे में गंध करते हैं, मैं सिर्फ यकीन है कि क्या नहीं कर रहा हूँ। ऐसा नहीं है कि वास्तव में वास्तव में वास्तव में कॉलम गणना बनाने वाले केवल एक कारखाने हैं - हालांकि मेरे कार्यक्रमों की अधिक आवश्यकता नहीं है।

क्या यह सबसे अच्छा अभ्यास माना जाता है? क्या मुझे इन्हें कुछ (अर्द्ध) वैश्विक ऐपकॉन्टेक्स्ट क्लास में सामान देना चाहिए? कुछ और (मैं कुछ बड़े आईओसी कंटेनर, या spring.net पर स्विच करने के लिए काफी तैयार नहीं हूँ अभी तक बीटीडब्ल्यू)?

उत्तर

11

यह वास्तव में आप क्या कर रहे हैं और आपके आवेदन का दायरा पर निर्भर करता है। यदि यह सिर्फ एक छोटा सा ऐप है और यह इससे आगे बढ़ने वाला नहीं है, तो आपका वर्तमान दृष्टिकोण ठीक हो सकता है। इन चीजों के लिए कोई सार्वभौमिक "सर्वश्रेष्ठ" अभ्यास नहीं है। जबकि मैं स्टेटलेस लीफ विधियों और/या एक तरफा कॉल (उदा। लॉगिंग) के अलावा किसी अन्य चीज़ के लिए सिंगलेट का उपयोग करने की अनुशंसा नहीं करता, क्योंकि इसे एक हाथ से बाहर निकालना 'जरूरी नहीं है' यह एक सिंगलटन आवश्यक नहीं है।

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

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

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

return new CalculationFactory(); 

:

3

क्या यह सर्वोत्तम अभ्यास माना जाता है?

मुझे कोई समस्या नहीं देखते हैं: आप ने कहा, "मेरे कार्यक्रमों में अधिक की जरूरत नहीं है", इसलिए अपने को लागू करने के लिए कुछ भी और अधिक लचीला/सार You Ain't Gonna Need It का मामला हो सकता है।

6

नहीं, क्योंकि आप यहां क्या कर रहे हैं वैश्विक स्थिति बना रहा है। वैश्विक राज्य के साथ सभी तरह की समस्याएं हैं- उनमें से एक प्रमुख है कि एक समारोह तब अन्य कार्यों के व्यवहार पर अदृश्य तरीके से निर्भर करता है। यदि कोई फ़ंक्शन किसी अन्य फ़ंक्शन को कॉल करता है जो इसे समाप्त होने से पहले factory को स्टोर और पुनर्स्थापित करना भूल जाता है, तो आपको एक समस्या है क्योंकि जब तक आप इसे कहीं भी संग्रहीत नहीं करते हैं तब तक आपको पुराना मान वापस नहीं मिल सकता है। और आपको ऐसा करने के लिए कोड जोड़ना होगा (आपके कोड द्वारा निर्णय लेना, मुझे लगता है कि आप finally वाली भाषा में हैं, जो गलतियों के लिए और भी अधिक जगह छोड़ देता है)। और भी, यदि आप कोड के साथ समाप्त होते हैं जिसे दो उपनिवेशों के लिए दो कारखानों के बीच जल्दी से स्विच करने की आवश्यकता होती है, तो आपको प्रत्येक बिंदु पर एक विधि कॉल लिखनी होगी - आप प्रत्येक सबोबजेक्ट में राज्य को स्टोर नहीं कर सकते हैं (ठीक है, आप कर सकते हैं, लेकिन फिर आप वैश्विक राज्य के उद्देश्य को हराते हैं [जो स्वीकार्य रूप से ज्यादा नहीं है])।

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

+0

हालांकि खुला सार्वजनिक सेटफैक्टरी को देखते हुए कोई गारंटी नहीं है कि कोई कारखाने के साथ और अधिक गड़बड़ी नहीं कर सकता है, मैं आमतौर पर प्रारंभिक desicion या विन्यास के आधार पर स्टार्टअप पर कारखाना सेट करने लगते हैं। – leeeroy

+0

तो आप सिंगलेट्स की कमी का शिकार हो जाते हैं ... वे सिंगलेट हैं। – coppro

4

मैं इसके खिलाफ सलाह दूंगा, क्योंकि यह उन कारखानों को कॉल करने वाले कोड के लिए सभ्य इकाई परीक्षण लिखना बहुत मुश्किल बनाता है।

मिस्को हेवरी के पास उनके ब्लॉग पर nice article है।

+0

उपर्युक्त कोड के साथ आप आसानी से एक कारखाने का नकल कर सकते हैं। – nos

+0

निश्चित रूप से, लेकिन क्या आप तुरंत जान लेंगे कि आपको किसके लिए नकल करना है, एक गैर-तुच्छ ऐप में जहां आप दिल की निर्भरता को दिल से नहीं जानते हैं? फिर, मैं मिस्को के लेख का संदर्भ देता हूं। – jqno

+0

मिस्को के पास इस विषय पर यूट्यूब पर कुछ उत्कृष्ट वीडियो भी हैं, http://www.youtube.com/watch?v=acjvKJiOvXw – Despertar

11

कुछ सिंगलेट्स होने के कारण बहुत आम है और आम तौर पर समस्याग्रस्त नहीं है - बहुत सारे सिंगलेट्स कुछ परेशान कोड की ओर ले जाते हैं।

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

एक साधारण फिक्स परीक्षण उद्देश्यों के लिए आपके सभी सिंगलेट्स के लिए "सेटर्स" रखना है। वास्तव में अनुशंसित नहीं है।

हमने एक और चीज की कोशिश की थी जिसमें एक एकल वर्ग था जिसमें सभी सिंगलेट्स - एक रजिस्ट्री थी। ऐसा करने से निर्भरता इंजेक्शन के बहुत करीब हो रहा है, जो आपको लगभग निश्चित रूप से उपयोग करना चाहिए।

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

किसी भी दर पर, DI में देखें, आप वास्तव में खुश हो सकते हैं।

+0

सहमत हैं। एकल परीक्षणों के दौरान सिंगलटन का एक और परिणाम सेट मूल्यों के "लीकिंग" है। हमें प्रत्येक परीक्षण के लिए जेवीएम को फोर्क करने का नतीजा हुआ है, क्योंकि एक सिंगलटन अंडर-टेस्ट या सिर्फ परीक्षण द्वारा उपयोग किया जाता है, राज्य ए में था, और डाउनस्ट्रीम को राज्य बी में होना आवश्यक था। – Trenton

+0

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

+0

मैं टीडीडी के बारे में सहमत हूं, लेकिन डीआई का उपयोग करने का यही एकमात्र कारण नहीं है। इसके अलावा, परीक्षण के वास्तविक अस्तित्व के बावजूद, टेस्टबल कोड आमतौर पर अवांछनीय कोड से बेहतर होगा। एक सिंगलटन के बजाय DI रखना कभी भी बुरा नहीं होता है और वास्तव में उस मामले में अच्छा हो सकता है जहां आप वास्तव में इसका परीक्षण करना चाहते हैं, भले ही आपके पास 100% परीक्षण कवरेज न हो। –

1

सिंगलटन का बुरा रूप है कि एक के साथ अपने फैक्टरी विधि के बराबर लागू करता है।

संस्करण जो कहीं और बनाया गया ऑब्जेक्ट देता है वह बहुत बेहतर है, हालांकि अधिकांश चीज़ों की तरह, इसका दुरुपयोग या उपयोग किया जा सकता है।

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