गौरवशाली वैश्विक चर - गौरवशाली वैश्विक वर्ग बन जाता है। कुछ लोग ऑब्जेक्ट-ओरिएंटेड डिज़ाइन को तोड़ते हैं।
मुझे अच्छे पुराने लकड़हारे के अलावा अन्य परिदृश्य दें, जहां यह सिंगलटन का उपयोग करने के लिए समझ में आता है।
गौरवशाली वैश्विक चर - गौरवशाली वैश्विक वर्ग बन जाता है। कुछ लोग ऑब्जेक्ट-ओरिएंटेड डिज़ाइन को तोड़ते हैं।
मुझे अच्छे पुराने लकड़हारे के अलावा अन्य परिदृश्य दें, जहां यह सिंगलटन का उपयोग करने के लिए समझ में आता है।
जवाबों:
सत्य की मेरी खोज पर मुझे पता चला कि एक सिंगलटन का उपयोग करने के वास्तव में बहुत कम "स्वीकार्य" कारण हैं।
एक कारण जो इंटर्नट्स पर बार-बार आने के लिए होता है, वह है "लॉगिंग" क्लास (जिसका आपने उल्लेख किया है)। इस स्थिति में, एक एकल वर्ग के एक उदाहरण के बजाय एक सिंगलटन का उपयोग किया जा सकता है क्योंकि एक लॉगिंग क्लास को आमतौर पर एक परियोजना में प्रत्येक वर्ग द्वारा बार-बार विज्ञापन के साथ उपयोग करने की आवश्यकता होती है। यदि हर वर्ग इस लॉगिंग क्लास का उपयोग करता है, तो निर्भरता इंजेक्शन बोझिल हो जाता है।
लॉगिंग "स्वीकार्य" सिंगलटन का एक विशिष्ट उदाहरण है क्योंकि यह आपके कोड के निष्पादन को प्रभावित नहीं करता है। लॉगिंग अक्षम करें, कोड निष्पादन समान है। इसे सक्षम करें, वही। मिसको इसे सिंगनलों के रूट कॉज़ में निम्नलिखित तरीके से डालता है , "यहां की जानकारी एक तरह से प्रवाहित होती है: आपके एप्लिकेशन से लकड़हारे से। भले ही लॉगर वैश्विक स्थिति हो, क्योंकि लॉगर से कोई भी जानकारी आपके आवेदन में प्रवाहित नहीं होती है, लकड़हारा स्वीकार्य हैं।"
मुझे यकीन है कि अन्य वैध कारण भी हैं। एलेक्स मिलर, में " पैटर्न आई हेट " में, सेवा लोकेटरों और क्लाइंट साइड यूआई की भी संभवतः "स्वीकार्य" पसंद की बात हो रही है।
और अधिक पढ़ें सिंगलटन आई लव यू, लेकिन आप मुझे नीचे ला रहे हैं।
सिंगलटन उम्मीदवार को तीन आवश्यकताओं को पूरा करना चाहिए:
यदि आपके प्रस्तावित सिंगलटन के पास इन आवश्यकताओं में से केवल एक या दो हैं, तो एक रीडिज़ाइन लगभग हमेशा सही विकल्प होता है।
उदाहरण के लिए, एक प्रिंटर स्पूलर को एक से अधिक स्थानों (प्रिंट मेनू) से कॉल करने की संभावना नहीं है, इसलिए आप समवर्ती पहुंच समस्या को हल करने के लिए म्यूटेक्स का उपयोग कर सकते हैं।
एक साधारण लकड़हारा संभवतः-वैध सिंगलटन का सबसे स्पष्ट उदाहरण है, लेकिन यह अधिक जटिल लॉगिंग योजनाओं के साथ बदल सकता है।
कॉन्फ़िगरेशन फ़ाइलों को पढ़ना जो केवल स्टार्टअप समय पर पढ़ा जाना चाहिए और उन्हें सिंगलटन में इनकैप्सुलेट करना चाहिए।
Properties.Settings.Default
.NET में।
जब आप किसी साझा संसाधन को प्रबंधित करने की आवश्यकता होती है, तो आप एक सिंगलटन का उपयोग करते हैं। उदाहरण के लिए एक प्रिंटर स्पूलर। आपके आवेदन में स्पूलर का एक ही उदाहरण होना चाहिए ताकि एक ही संसाधन के लिए परस्पर विरोधी अनुरोध न हो।
या एक डेटाबेस कनेक्शन या एक फ़ाइल प्रबंधक आदि।
कुछ वैश्विक राज्य (उपयोगकर्ता की भाषा, मदद फ़ाइलपथ, आवेदन पथ) को संग्रहीत करने वाले केवल एकल ही पढ़ें उचित हैं। व्यापार तर्क को नियंत्रित करने के लिए सिंगलटन का उपयोग करने में सावधानी बरतें - सिंगल लगभग हमेशा मल्टीपल होता है
एक डेटाबेस के लिए एक कनेक्शन (या कनेक्शन का एक पूल) का प्रबंधन।
मैं इसका उपयोग बाहरी विन्यास फाइल पर informations को पुनः प्राप्त करने और संग्रहीत करने के लिए भी करूंगा।
आपके द्वारा सिंगलटन का उपयोग करने के तरीकों में से एक उदाहरण को कवर करना है जहां एक संसाधन तक पहुंच को नियंत्रित करने वाला एकल "ब्रोकर" होना चाहिए। सिंगलर्स लॉगर में अच्छे होते हैं क्योंकि वे ब्रोकर तक पहुंचते हैं, कहते हैं, एक फाइल, जो केवल विशेष रूप से लिखी जा सकती है। लॉगिंग जैसी किसी चीज़ के लिए, वे राइट्स को लॉग फ़ाइल की तरह कुछ को अलग करने का एक तरीका प्रदान करते हैं - आप अपने सिंग्लटन को एक कैशिंग तंत्र लपेट सकते हैं, आदि ...
ऐसी स्थिति के बारे में भी सोचें जहां आपके पास कई विंडोज़ / थ्रेड / आदि के साथ एक एप्लिकेशन है, लेकिन जिसे संचार के एक बिंदु की आवश्यकता है। मैंने एक बार नौकरियों को नियंत्रित करने के लिए एक का उपयोग किया था जिसे मैं लॉन्च करने के लिए अपना आवेदन चाहता था। सिंगलटन नौकरियों को क्रमबद्ध करने और कार्यक्रम के किसी अन्य भाग में अपनी स्थिति प्रदर्शित करने के लिए जिम्मेदार था, जो रुचि रखते थे। इस प्रकार के परिदृश्य में, आप अपने अनुप्रयोग के अंदर चल रहे "सर्वर" वर्ग की तरह किसी सिंगलटन को देख सकते हैं ... HTH
एक सिंगलटन का उपयोग एक संसाधन तक पहुंच का प्रबंधन करते समय किया जाना चाहिए जो पूरे एप्लिकेशन द्वारा साझा किया जाता है, और यह संभवतः एक ही वर्ग के कई उदाहरणों के लिए विनाशकारी होगा। यह सुनिश्चित करना कि साझा संसाधन थ्रेड तक पहुँच सुरक्षित है, इस तरह का पैटर्न महत्वपूर्ण हो सकता है।
सिंग्लेटन्स का उपयोग करते समय, आपको यह सुनिश्चित करना चाहिए कि आप गलती से निर्भरता को छिपा नहीं रहे हैं। आदर्श रूप से, एकल (किसी एप्लिकेशन में अधिकांश स्थिर चर की तरह) अनुप्रयोग के लिए आपके आरंभीकरण कोड के निष्पादन के दौरान स्थापित किया जाता है (C # निष्पादक के लिए स्थैतिक शून्य मुख्य), जावा निष्पादन के लिए स्थैतिक शून्य मुख्य () और फिर में उत्तीर्ण किया जाता है। अन्य सभी वर्ग जो तात्कालिक हैं जिन्हें इसकी आवश्यकता है। यह आपको परीक्षण क्षमता बनाए रखने में मदद करता है।
एक सिंगलटन का एक व्यावहारिक उदाहरण टेस्ट :: बिल्डर में पाया जा सकता है , वह वर्ग जो हर आधुनिक पर्ल परीक्षण मॉड्यूल के बारे में बताता है। टेस्ट :: बिल्डर सिंगलटन स्टोर और दलालों का परीक्षण प्रक्रिया की स्थिति और इतिहास (ऐतिहासिक परीक्षण के परिणाम, परीक्षण की संख्या की गणना करता है) के साथ-साथ उन चीजों को भी शामिल करता है, जहां परीक्षण आउटपुट हो रहा है। ये सभी अलग-अलग लेखकों द्वारा लिखित कई परीक्षण मॉड्यूल को समन्वित करने के लिए आवश्यक हैं, एक परीक्षण स्क्रिप्ट में एक साथ काम करने के लिए।
टेस्ट का इतिहास :: बिल्डर का सिंगलटन शैक्षिक है। new()
हमेशा कॉल करना आपको एक ही वस्तु देता है। सबसे पहले, सभी डेटा को केवल ऑब्जेक्ट में कुछ भी नहीं के साथ वर्ग चर के रूप में संग्रहीत किया गया था। यह तब तक काम किया जब तक मैं टेस्ट का परीक्षण नहीं करना चाहता था :: बिल्डर खुद के साथ। तब मुझे दो टेस्ट की आवश्यकता थी :: बिल्डर ऑब्जेक्ट्स, एक डमी के रूप में एक सेटअप, इसके व्यवहार और आउटपुट को पकड़ने और परीक्षण करने के लिए, और असली टेस्ट ऑब्जेक्ट होने के लिए। उस बिंदु पर परीक्षण :: बिल्डर को वास्तविक वस्तु में बदल दिया गया था। सिंगलटन ऑब्जेक्ट को क्लास डेटा के रूप में संग्रहीत किया गया था, और new()
हमेशा इसे वापस करेगा। create()
एक नई वस्तु बनाने और परीक्षण सक्षम करने के लिए जोड़ा गया था।
वर्तमान में, उपयोगकर्ता अपने स्वयं के मॉड्यूल में टेस्ट :: बिल्डर के कुछ व्यवहारों को बदलना चाहते हैं, लेकिन दूसरों को अकेला छोड़ देते हैं, जबकि परीक्षण इतिहास सभी परीक्षण मॉड्यूल में आम है। अब जो हो रहा है वह है अखंड परीक्षण :: बिल्डर ऑब्जेक्ट को छोटे टुकड़ों (इतिहास, आउटपुट, प्रारूप ...) में तोड़ा जा रहा है, टेस्ट :: बिल्डर उदाहरण उन्हें एक साथ इकट्ठा कर रहा है। अब टेस्ट :: बिल्डर को अब एक सिंगलटन होना चाहिए। इसके घटक, जैसे इतिहास, हो सकते हैं। यह एक सिंगलटन की अनम्य आवश्यकता को एक स्तर से नीचे धकेलता है। यह उपयोगकर्ता को मिक्स-एंड-मैच टुकड़ों को अधिक लचीलापन देता है। छोटी सिंगलटन ऑब्जेक्ट्स अब डेटा स्टोर कर सकती हैं, जिसमें उनकी ऑब्जेक्ट्स का उपयोग करने का निर्णय लेना है। यहां तक कि यह एक गैर-टेस्ट :: बिल्डर वर्ग को टेस्ट :: बिल्डर इतिहास और आउटपुट एकल का उपयोग करके खेलने की अनुमति देता है।
लगता है कि डेटा के समन्वय और व्यवहार के लचीलेपन के बीच एक धक्का और पुल है जो डेटा अखंडता को सुनिश्चित करने के लिए जितना संभव हो सके कम से कम व्यवहार के साथ एकल साझा डेटा के आसपास सिंगलटन डालकर कम किया जा सकता है।
जब आप कॉन्फ़िगरेशन गुण ऑब्जेक्ट लोड करते हैं, तो डेटाबेस या फ़ाइल से, यह एक सिंगलटन के रूप में होने में मदद करता है; स्थिर डेटा को फिर से पढ़ने का कोई कारण नहीं है जो सर्वर के चलने के दौरान नहीं बदलेगा।
राज्य पैटर्न (गोफ बुक में दिखाए गए तरीके से) को लागू करते समय आप सिंगलटन का उपयोग कर सकते हैं। इसका कारण यह है कि ठोस राज्य वर्गों का अपना कोई राज्य नहीं है, और एक संदर्भ वर्ग के संदर्भ में अपने कार्यों का प्रदर्शन करते हैं।
आप एब्सट्रैक्ट फैक्ट्री को सिंगलटन भी बना सकते हैं।
setState()
राज्य निर्माण नीति तय करने के लिए अपनी ज़िम्मेदारी बनाने की कोशिश करें । यदि आपकी प्रोग्रामिंग भाषा टेम्प्लेट या जेनरिक का समर्थन करती है तो यह मदद करता है। सिंगलटन के बजाय, आप मोनोस्टेट पैटर्न का उपयोग कर सकते हैं , जहां एक राज्य वस्तु को इंस्टेंट करना उसी वैश्विक / स्थिर राज्य वस्तु का पुन: उपयोग कर रहा है। राज्य को बदलने के लिए वाक्यविन्यास अपरिवर्तित रह सकता है, क्योंकि आपके उपयोगकर्ताओं को यह पता होने की आवश्यकता नहीं है कि तात्कालिक स्थिति एक मोनोस्टेट है।
साझा किए गए संसाधन। विशेष रूप से PHP में, एक डेटाबेस वर्ग, एक टेम्पलेट वर्ग, और एक वैश्विक चर डिपो वर्ग। सभी को सभी मॉड्यूल / वर्गों द्वारा साझा किया जाना है जो पूरे कोड में उपयोग किए जा रहे हैं।
यह एक सच्ची वस्तु का उपयोग है -> टेम्प्लेट क्लास में पेज टेम्प्लेट होता है जिसे बनाया जा रहा है, और यह पृष्ठ आउटपुट में जोड़ रहे मॉड्यूल द्वारा आकार, जोड़ा, बदल जाता है। इसे एक ही उदाहरण के रूप में रखा जाना चाहिए ताकि यह हो सके, और डेटाबेस के लिए समान हो। एक साझा डेटाबेस सिंगलटन के साथ, सभी मॉड्यूल की कक्षाएं प्रश्नों तक पहुंच प्राप्त कर सकती हैं और उन्हें पुनः प्राप्त किए बिना प्राप्त कर सकती हैं।
एक वैश्विक चर डिपो सिंगलटन आपको एक वैश्विक, विश्वसनीय और आसानी से उपयोग करने योग्य चर डिपो प्रदान करता है। यह आपके कोड को बहुत बढ़िया बनाता है। किसी एकल में सरणी में सभी कॉन्फ़िगरेशन मान होने की कल्पना करें जैसे:
$gb->config['hostname']
या किसी सरणी में सभी भाषा मान जैसे:
$gb->lang['ENTER_USER']
पृष्ठ के लिए कोड चलाने के अंत में, आप कहते हैं, अब परिपक्व हो जाओ:
$template
सिंगलटन, एक $gb
सिंगलटन जिसमें इसे बदलने के लिए लैंग एरे है, और सभी आउटपुट लोड और तैयार हैं। आप बस उन्हें उन कुंजियों में बदल देते हैं जो अब परिपक्व टेम्प्लेट ऑब्जेक्ट के पेज वैल्यू में मौजूद हैं, और फिर इसे उपयोगकर्ता को दिखाते हैं।
इसका महान लाभ यह है कि आप किसी भी चीज़ पर अपनी पसंद के बाद की प्रोसेसिंग कर सकते हैं। आप सभी भाषा मूल्यों को Google अनुवाद, या किसी अन्य अनुवाद सेवा में पाइप कर सकते हैं और उन्हें वापस ला सकते हैं, और उन्हें अपने स्थानों में बदल सकते हैं, उदाहरण के लिए, अनुवादित। या, आप चाहते हैं कि आप पृष्ठ संरचनाओं में बदल सकते हैं, या, सामग्री स्ट्रिंग,।
यह विशिष्ट बुनियादी ढांचा चिंताओं को एकल या वैश्विक चर के रूप में कॉन्फ़िगर करने के लिए बहुत ही व्यावहारिक हो सकता है। इसका मेरा पसंदीदा उदाहरण डिपेंडेंसी इंजेक्शन चौखटे हैं जो फ्रेमवर्क से कनेक्शन बिंदु के रूप में कार्य करने के लिए एकल का उपयोग करते हैं।
इस मामले में आप लाइब्रेरी के उपयोग को आसान बनाने और अनपेक्षित जटिलता से बचने के लिए बुनियादी ढांचे पर निर्भरता ले रहे हैं।
प्लग-योग्य मॉड्यूल के साथ काम करते समय कमांड-लाइन मापदंडों को एनकैप्सुलेट करने वाले ऑब्जेक्ट के लिए मैं इसका उपयोग करता हूं। मुख्य कार्यक्रम को पता नहीं है कि कमांड-लाइन पैरामीटर उन मॉड्यूल के लिए क्या हैं जो लोड हो जाते हैं (और हमेशा यह भी नहीं जानते हैं कि मॉड्यूल क्या लोड किया जा रहा है)। उदाहरण के लिए, मुख्य भार A, जिसे स्वयं किसी भी पैरामीटर की आवश्यकता नहीं है (इसलिए इसे अतिरिक्त पॉइंटर / संदर्भ / जो भी हो, मुझे यकीन नहीं है - प्रदूषण की तरह दिखता है), फिर मॉड्यूल X, Y और Z दो लोड करता है। इनमें से, X और Z, ज़रूरत (या स्वीकार) मापदंडों का कहना है, इसलिए वे कमांड-लाइन सिंगलटन को यह बताने के लिए वापस बुलाते हैं कि कौन से पैरामीटर को स्वीकार करना है, और रनटाइम में वे यह पता लगाने के लिए वापस कॉल करते हैं कि क्या उपयोगकर्ता ने वास्तव में कोई निर्दिष्ट किया है उनमें से।
कई मायनों में, सीजीआई मापदंडों को संभालने के लिए एक सिंगलटन इसी तरह काम करेगा यदि आप प्रति क्वेरी केवल एक प्रक्रिया का उपयोग कर रहे हैं (अन्य mod_ * विधियां ऐसा नहीं करती हैं, इसलिए यह वहां बुरा होगा - इस प्रकार तर्क जो आपको कहना चाहिए ' यदि आप mod_perl या जो भी दुनिया में पोर्ट करते हैं, तो mod_cgi दुनिया में सिंगललेट्स का उपयोग करें।
कोड के साथ एक उदाहरण, शायद।
यहाँ, कंकरीट नैन्सी एक पोकर गेम में एक सिंगलटन है जो पैकेज ट्री तक सभी तरह से व्यवहार को अनुमति देता है, खेल के कुछ प्रमुख इंटरफेस (यानी, मॉडल, दृश्य, नियंत्रक, पर्यावरण, आदि के लिए facades)।
http://www.edmundkirwan.com/servlet/fractal/cs1/frac-cs40.html
ईडी।
1 - पहले उत्तर पर एक टिप्पणी:
मैं एक स्थिर लकड़हारा वर्ग से सहमत नहीं हूँ। यह एक कार्यान्वयन के लिए व्यावहारिक हो सकता है, लेकिन यह इकाई परीक्षण के लिए बदली नहीं जा सकता है। एक स्थिर वर्ग को परीक्षण डबल द्वारा प्रतिस्थापित नहीं किया जा सकता है। यदि आप इकाई परीक्षण नहीं करते हैं, तो आप यहाँ समस्या नहीं देखेंगे।
2 - मैं हाथ से एक सिंगलटन नहीं बनाने की कोशिश करता हूं। मैं बस एक सरल वस्तु का निर्माण करता हूं जिसमें निर्माता हैं जो मुझे ऑब्जेक्ट में सहयोगियों को इंजेक्ट करने की अनुमति देते हैं। अगर मुझे एक सिंगलटन की आवश्यकता है, तो मैं एक निर्भरता फ्रेमवर्क (स्प्रिंग.नेट, यूनिटी फॉर .NET, जावा के लिए स्प्रिंग), या कुछ अन्य का उपयोग करूंगा।
ILogger logger = Logger.SingleInstance();
जहां यह विधि स्थिर है और यह एक ILogger के एक स्टेटिक रूप से संग्रहीत उदाहरण देता है। आपने "एक निर्भरता इंजेक्शन ढांचे" के उदाहरण का उपयोग किया। लगभग सभी DI कंटेनर सिंगलटन हैं; उनके कॉन्फ़िगरेशन को सांख्यिकीय रूप से परिभाषित किया गया है और अंततः एकल सेवा प्रदाता इंटरफ़ेस में / से संग्रहीत किया गया है।