सिंगलटन: इसका उपयोग कैसे किया जाना चाहिए


291

संपादित करें: एक अन्य प्रश्न से मैंने एक उत्तर प्रदान किया जिसमें बहुत सारे प्रश्नों के लिंक / उत्तर दिए गए हैं: एकल गीतों के बारे में अधिक जानकारी:

इसलिए मैंने थ्रेड सिंगलेट्स पढ़ा है : अच्छा डिज़ाइन या बैसाखी?
और तर्क अभी भी गुस्से में है।

मैं सिंगलेट्स को एक डिज़ाइन पैटर्न (अच्छे और बुरे) के रूप में देखता हूं।

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

तो मुख्य सवालों के जवाब देने की जरूरत है:

  • आपको एक सिंगलटन का उपयोग कब करना चाहिए
  • आप एक सिंगलटन को सही तरीके से कैसे लागू करते हैं

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


इसलिए गेंद को घुमाएं:
मैं अपना हाथ ऊपर करूंगा और यह कहूंगा कि मैं इसका उपयोग करता हूं लेकिन शायद समस्या है।
मुझे "स्कॉट मायर्स" अपनी किताब "प्रभावी सी ++" में विषय को संभालना पसंद है

सिंगलेट्स (बहुत सारे नहीं) का उपयोग करने के लिए अच्छी स्थिति:

  • लॉगिंग चौखटे
  • थ्रेड रीसाइक्लिंग पूल
/*
 * C++ Singleton
 * Limitation: Single Threaded Design
 * See: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
 *      For problems associated with locking in multi threaded applications
 *
 * Limitation:
 * If you use this Singleton (A) within a destructor of another Singleton (B)
 * This Singleton (A) must be fully constructed before the constructor of (B)
 * is called.
 */
class MySingleton
{
    private:
        // Private Constructor
        MySingleton();
        // Stop the compiler generating methods of copy the object
        MySingleton(MySingleton const& copy);            // Not Implemented
        MySingleton& operator=(MySingleton const& copy); // Not Implemented

    public:
        static MySingleton& getInstance()
        {
            // The only instance
            // Guaranteed to be lazy initialized
            // Guaranteed that it will be destroyed correctly
            static MySingleton instance;
            return instance;
        }
};

ठीक है। चलो कुछ आलोचना और अन्य कार्यान्वयन एक साथ मिलें।
:-)


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

3
किसने कहा कि एक रूपरेखा में केवल 1 लकड़हारा उदाहरण हो सकता है। फ्रेमवर्क का प्रतिनिधित्व करने वाला एक सिंगलटन। फिर फ़्रेमवर्क आपको विशिष्ट लकड़हारा दे सकता है।
मार्टिन यॉर्क

हाँ। मैं थ्रेड के रूप में एक सिंगेलोंग का उपयोग नहीं करूंगा। बस जवाबों को उगलने के लिए विचारों को बाहर फेंक रहे हैं।
मार्टिन यॉर्क

@Dan सिंगलटन जो रणनीति पैटर्न को लागू करता है। व्यवहार एकल से अमूर्त है। सिंगलटन प्रवेश का एकल बिंदु है। दो लकड़हारे नहीं हैं, एक लकड़हारा है जो तय कर सकता है कि उसे कैसे लॉग इन करना है। आप केवल एक समय में एक लॉग में आउटपुट नहीं कर सकते, दो की आवश्यकता नहीं है।
ली लौविएरे

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

जवाबों:


182

आप सभी गलत हैं। प्रश्न पढ़ें। उत्तर:

एक सिंगलटन का उपयोग करें यदि:

  • आपको सिस्टम में एक प्रकार का एक और केवल एक ऑब्जेक्ट होना चाहिए

एक सिंगलटन का उपयोग न करें यदि:

  • आप स्मृति को बचाना चाहते हैं
  • आप कुछ नया करने की कोशिश करना चाहते हैं
  • आप दिखाना चाहते हैं कि आप कितना जानते हैं
  • क्योंकि हर कोई इसे कर रहा है ( विकिपीडिया में कार्गो पंथ प्रोग्रामर देखें )
  • यूजर इंटरफेस विगेट्स में
  • इसे कैची माना जाता है
  • तार में
  • सत्रों में
  • मैं दिन भर जा सकता हूं

कैसे सर्वश्रेष्ठ सिंगलटन बनाने के लिए:

  • जितना छोटा, उतना अच्छा। मैं एक न्यूनतावादी हूं
  • सुनिश्चित करें कि यह धागा सुरक्षित है
  • सुनिश्चित करें कि यह कभी भी अशक्त नहीं है
  • सुनिश्चित करें कि यह केवल एक बार बनाया गया है
  • आलसी या सिस्टम इनिशियलाइज़ेशन? अपनी आवश्यकताओं के अनुसार
  • कभी-कभी OS या JVM आपके लिए सिंगलटन बनाता है (जैसे जावा में हर वर्ग की परिभाषा एक सिंगलटन है)
  • एक विध्वंसक प्रदान करना या किसी तरह से यह पता लगाना कि संसाधनों का निपटान कैसे करना है
  • छोटी मेमोरी का उपयोग करें

14
दरअसल, मुझे लगता है कि आप बिलकुल भी सही नहीं हैं। मैं के रूप में अलग तरीके से व्यक्त करता हूँ: "आप अगर जरूरत एक और प्रणाली में एक प्रकार का केवल एक वस्तु के लिए और आप की जरूरत है इसे करने के लिए वैश्विक उपयोग करने के लिए" की आवश्यकता पर जोर मेरा है - यह मत करो अगर इसके सुविधाजनक, केवल आप अगर यह होना चाहिए।

91
तुम भी गलत हो। यदि आपको एक और केवल एक वस्तु की आवश्यकता है, तो आप एक और केवल एक ही बनाते हैं। यदि कोई तार्किक तरीका नहीं है कि दो उदाहरणों को कभी भी अपरिवर्तनीय रूप से आवेदन को भ्रष्ट किए बिना ही हटाया जा सकता है, तो आपको इसे एक सिंगलटन बनाने पर विचार करना चाहिए। और फिर इसका दूसरा पहलू है, वैश्विक पहुंच: यदि आपको उदाहरण के लिए वैश्विक पहुंच की आवश्यकता नहीं है, तो यह एकल नहीं होना चाहिए।
१।'०

4
संशोधन के लिए बंद, विस्तार के लिए खुला। समस्या यह है कि आप एक सिंगलटन को डयूटन या ट्रिपलटन के रूप में विस्तारित नहीं कर सकते हैं। यह एक एकल के रूप में अटक गया है।
ली लुईविअर

2
@ enzom83: एक राजधानी-एस सिंगलटन में इसकी एकलता सुनिश्चित करने के लिए कोड शामिल है। यदि आप केवल एक उदाहरण चाहते हैं, तो आप उस कोड को खो सकते हैं और बस एक उदाहरण खुद बना सकते हैं ... आपको एक एकल उदाहरण की मेमोरी बचत दे सकते हैं, साथ ही विलक्षणता को लागू करने से होने वाली बचत - लागू करने का अर्थ है - जिसका अर्थ बलिदान करना भी नहीं है अगर आपकी आवश्यकताओं में कभी बदलाव होता है, तो दूसरा उदाहरण बनाने की क्षमता।
cHao

4
"यदि आपको सिस्टम में एक प्रकार का एक और केवल एक ऑब्जेक्ट होना चाहिए" - "... और एक यूनिट टेस्ट में उस ऑब्जेक्ट का कभी भी मजाक नहीं करना चाहिए।"
साइगॉन

72

सिंगलटन आपको एक कक्षा में दो बुरे लक्षणों को संयोजित करने की क्षमता देता है। यह बहुत ज्यादा हर तरह से गलत है।

एक सिंगलटन आपको देता है:

  1. किसी वस्तु तक वैश्विक पहुंच, और
  2. एक गारंटी कि इस प्रकार की एक से अधिक वस्तु कभी नहीं बनाई जा सकती है

नंबर एक सीधा है। ग्लोबल्स आमतौर पर खराब होते हैं। जब तक हमें वास्तव में इसकी आवश्यकता नहीं है, तब तक हमें विश्व स्तर पर वस्तुओं को कभी सुलभ नहीं बनाना चाहिए ।

नंबर दो की तरह लग सकता है यह समझ में आता है, लेकिन चलो इसके बारे में सोचते हैं। पिछली बार जब आपने ** गलती से * एक मौजूदा वस्तु को संदर्भित करने के बजाय एक नई वस्तु बनाई थी? चूंकि यह C ++ टैग है, इसलिए उस भाषा से एक उदाहरण का उपयोग करें। क्या आप अक्सर गलती से लिखते हैं

std::ostream os;
os << "hello world\n";

जब लिखने का इरादा किया

std::cout << "hello world\n";

बिलकूल नही। हमें इस त्रुटि से सुरक्षा की आवश्यकता नहीं है, क्योंकि उस तरह की त्रुटि अभी नहीं हुई है। यदि ऐसा होता है, तो सही प्रतिक्रिया घर जाकर 12-20 घंटे सोना है और आशा है कि आप बेहतर महसूस करेंगे।

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

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

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

यदि आपको किसी वस्तु तक वैश्विक पहुंच की आवश्यकता है, तो इसे एक वैश्विक बनाएं, जैसे std::cout। लेकिन ऐसे उदाहरणों की संख्या में कमी न करें जो बनाए जा सकते हैं।

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

यदि आपको दोनों लक्षणों की आवश्यकता है, तो 1) इसे एक सिंगलटन बनाएं, और 2) मुझे बताएं कि आपको इसके लिए क्या चाहिए, क्योंकि मुझे इस तरह के मामले की कल्पना करने में मुश्किल समय आ रहा है।


3
या आप इसे एक वैश्विक बना सकते हैं, और एक सिंगलटन के डाउनसाइड्स में से केवल एक प्राप्त कर सकते हैं । सिंगलटन के साथ, आप एक साथ अपने आप को उस डेटाबेस क्लैप्स के एक उदाहरण तक सीमित कर देंगे। ऐसा क्यों करते हैं? या आप देख सकते हैं कि आपके पास इतनी निर्भरता क्यों है कि तात्कालिकता सूची "वास्तव में लंबी" बन जाती है। क्या वे सभी आवश्यक हैं? क्या उनमें से कुछ को अन्य घटकों को सौंप दिया जाना चाहिए? शायद उनमें से कुछ को एक साथ एक संरचना में पैक किया जा सकता है ताकि हम उन्हें एक ही तर्क के रूप में पारित कर सकें। बहुत सारे समाधान हैं, उनमें से सभी एकल से बेहतर हैं।
जुलफ

6
हां, एक सिंगलटन को वहीं ठहराया जा सकता है। लेकिन मुझे लगता है कि आपने सिर्फ अपनी बात साबित की है कि यह केवल सुंदर विदेशी मामलों में ही आवश्यक है। अधिकांश सॉफ्टवेयर बर्फ की जुताई हार्डवेयर से नहीं होते हैं। लेकिन मैं अभी भी आश्वस्त नहीं हूं। मैं मानता हूं कि आपके वास्तविक आवेदन में आप केवल इनमें से एक चाहते हैं। लेकिन आपकी इकाई परीक्षणों के बारे में क्या? उनमें से प्रत्येक को अलगाव में चलना चाहिए, इसलिए उन्हें आदर्श रूप से अपना स्प्रेडरकंट्रोलर बनाना चाहिए - जो एक सिंगलटन के साथ करना मुश्किल है। अंत में, आपके सहकर्मी पहले स्थान पर कई उदाहरण क्यों बनाएंगे? क्या इससे बचाने के लिए एक यथार्थवादी परिदृश्य है?
जुलफ १५'०

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

2
@ jalf - मेरा लक्ष्य आपको केवल एक उदाहरण देना था कि सिंग्लटन जंगल में कहां उपयोगी है, क्योंकि आप कोई कल्पना नहीं कर सकते हैं; मुझे लगता है कि आप इसे अपने काम की वर्तमान पंक्ति को लागू करने के लिए कई बार नहीं देखते हैं। मैंने पूरी तरह से व्यावसायिक अनुप्रयोगों से बर्फ की हल प्रोग्रामिंग में स्विच किया क्योंकि यह मुझे सिंगलटन का उपयोग करने की अनुमति देगा। :) j / k मैं आपके आधार से सहमत हूं कि इन चीजों को करने के बेहतर तरीके हैं, आपने मुझे सोचने के लिए बहुत कुछ दिया है। चर्चा के लिए धन्यवाद!
जे। पोलर

2
लोगों को तुरंत ऐसा करने से रोकने के लिए सिंगलटन ( AHEM! ) "पैटर्न" का उपयोग करके लोगों को और अधिक इंस्टेंस को रोकने के लिए सादे पुराने बेवकूफ बनाया गया है। जब मेरे पास मेरे छोटे से फंक्शन में टाइप फू का एक स्थानीय वैरिएबल foo1 है और केवल एक फंक्शन में चाहते हैं, तो मुझे इस बात की चिंता नहीं है कि कोई व्यक्ति दूसरा फू वेरिएबल foo2 बनाने जा रहा है और मूल के बजाय इसका उपयोग कर रहा है।
थॉमस ईडिंग

36

एकल के साथ समस्या उनका कार्यान्वयन नहीं है। यह है कि वे दो अलग-अलग अवधारणाओं का सामना करते हैं, जिनमें से कोई भी स्पष्ट रूप से वांछनीय नहीं है।

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

2) एकल वर्ग के कई तात्कालिकता को रोकते हैं। यह दुर्लभ है, IME, कि इस तरह की सुविधा को एक वर्ग में बेक किया जाना चाहिए। यह सामान्य रूप से बहुत अधिक प्रासंगिक बात है; बहुत सी चीजें जो एक-और-एक के रूप में मानी जाती हैं, वे वास्तव में केवल-से-केवल-एक होती हैं। IMO एक अधिक उपयुक्त समाधान केवल एक उदाहरण बनाना है - जब तक आपको एहसास न हो कि आपको एक से अधिक उदाहरणों की आवश्यकता है।


6
माना। वास्तविक दुनिया में कुछ के अनुसार दो गलतियाँ एक अधिकार बना सकती हैं। लेकिन प्रोग्रामिंग में, दो बुरे विचारों को मिलाने से परिणाम अच्छा नहीं होता है।
:

27

पैटर्न के साथ एक बात: सामान्यीकरण न करें । उनके पास सभी मामले हैं जब वे उपयोगी होते हैं, और जब वे असफल होते हैं।

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

अन्य समस्या यह है कि वास्तव में सिंगलटन भेष में एक वैश्विक चर से अधिक कुछ नहीं है । जब आपके पास अपने कार्यक्रम पर बहुत अधिक वैश्विक साझा स्थिति होती है, तो चीजें वापस चली जाती हैं, हम सभी इसे जानते हैं।

यह निर्भरता ट्रैकिंग को कठिन बना सकता है। जब सब कुछ आपके सिंगलटन पर निर्भर करता है, तो इसे बदलना मुश्किल है, दो को विभाजित करना, आदि। आप आम तौर पर इसके साथ फंस गए हैं। इससे लचीलापन भी बाधित होता है। इस समस्या को कम करने के लिए कुछ निर्भरता इंजेक्शन ढांचे की जाँच करें।


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

7
यह भी ध्यान दिया जाना चाहिए कि एकल को सार्वजनिक पहुंच की आवश्यकता नहीं है। एक सिंगलटन बहुत अच्छी तरह से पुस्तकालय के लिए आंतरिक हो सकता है और कभी भी उपयोगकर्ता के सामने नहीं आ सकता है। इसलिए वे उस अर्थ में "वैश्विक" नहीं हैं।
स्टीवन एवर्स

1
+1 यह इंगित करने के लिए कि सिंगलेट्स परीक्षण में कितना दर्द कर रहे हैं।
देवसोलर

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

2
@William: और मुझे समय-समय पर कई लॉगर करने पड़ते हैं। आप एक एकल के लिए बहस नहीं कर रहे हैं, लेकिन एक सादे पुराने स्थानीय के लिए। आप जानना चाहते हैं कि एक लकड़हारा हमेशा उपलब्ध रहता है। यह एक वैश्विक के लिए है। आपको यह जानने की आवश्यकता नहीं है कि कोई भी अन्य लकड़हारा कभी भी तुरंत संभव नहीं हो सकता है , जो कि एक सिंगलटन लागू करता है। (अपने लकड़हारे के लिए इकाई परीक्षण लिखने की कोशिश करें - यह बहुत आसान है यदि आप इसे आवश्यकतानुसार बना सकते हैं और नष्ट कर सकते हैं, और यह एक सिंगलटन के साथ संभव नहीं है)
jalf

13

सिंगलेट्स मूल रूप से आपको भाषाओं में जटिल वैश्विक स्थिति देते हैं जो अन्यथा जटिल वैश्विक चर के लिए मुश्किल या असंभव बनाते हैं।

जावा विशेष रूप से वैश्विक चर के प्रतिस्थापन के रूप में एकल का उपयोग करता है, क्योंकि सब कुछ एक वर्ग के भीतर होना चाहिए। वैश्विक चर के सबसे करीब यह सार्वजनिक स्थैतिक चर हैं, जिनका उपयोग ऐसे किया जा सकता है जैसे कि वे वैश्विक थेimport static

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

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

तो सिंगलटन का उपयोग करना कब अच्छा / बुरा है? बहुत अच्छा है जब यह एक वैश्विक चर का उपयोग करने के लिए अच्छा / बुरा होगा।


जब कभी एक वैश्विक चर "अच्छा" होता है? कभी-कभी वे किसी समस्या के लिए सबसे अच्छा समाधान होते हैं, लेकिन वे कभी "अच्छे" नहीं होते हैं।
देवसोलर

1
वैश्विक चर अच्छा है जब इसे हर जगह उपयोग किया जाता है, और हर चीज की पहुंच हो सकती है। एकल राज्य ट्यूरिंग मशीन के कार्यान्वयन से सिंगलटन का उपयोग किया जा सकता है।
ली लुईविअर

मुझे इस उत्तर में अप्रत्यक्ष की परत पसंद है: "जब यह एक वैश्विक उपयोग करने के लिए अच्छा / बुरा होगा"। देवसोलर और ली लौविरे दोनों को वे मूल्य मिलते हैं, जिनसे वे सहमत होते हैं, हालांकि उत्तरकाल में यह पता नहीं चल सकता था कि कौन टिप्पणी करेगा।
प्रिक्सोलिटिक

6

अलेक्जेंड्रेस्कु द्वारा आधुनिक सी ++ डिजाइन में एक थ्रेड-सुरक्षित, अंतर्निहित जेनेरिक सिंगलटन है।

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


6
  • आप एक सिंगलटन को सही तरीके से कैसे लागू करते हैं

एक समस्या है जिसका मैंने कभी उल्लेख नहीं किया है, कुछ ऐसा है जिसे मैंने पिछली नौकरी में चलाया था। हमारे पास सी ++ सिंग्लेटलेट्स थे जो डीएलएल के बीच साझा किए गए थे, और सामान्य तौर पर एक वर्ग का एक ही उदाहरण सुनिश्चित करने के लिए काम नहीं करता है। समस्या यह है कि प्रत्येक DLL को EXE के साथ-साथ स्थिर चर का अपना सेट मिलता है। यदि आपका get_instance फ़ंक्शन इनलाइन या स्टैटिक लाइब्रेरी का हिस्सा है, तो प्रत्येक DLL "एकल" की अपनी प्रति के साथ प्रसारित होगा।

समाधान यह सुनिश्चित करने के लिए है कि सिंगलटन कोड केवल एक डीएलएल या ईएक्सई में परिभाषित किया गया है, या उन गुणों के साथ एक सिंगलटन प्रबंधक बनाएं जो उदाहरणों को पार्सल कर सकते हैं।


10
यो डॉग, मैंने सुना है कि आपको सिंग्लेटन्स पसंद है, इसलिए मैंने आपके सिंगलटन के लिए एक सिंगलटन बनाया है, इसलिए आप पैटर्न-विरोधी रहते हुए एंटी-पैटर्न कर सकते हैं।
ईवा

@ ईवा, हाँ ऐसा ही कुछ। मैंने समस्या नहीं बनाई, मुझे बस इसे किसी तरह काम करना था।
मार्क रैनसम

5

पहला उदाहरण थ्रेड सुरक्षित नहीं है - यदि दो थ्रेड्स कॉल करते हैं तो एक ही समय में, वह स्थैतिक एक PITA होने वाला है। म्यूटेक्स के कुछ रूप में मदद मिलेगी।


हां जो उपरोक्त टिप्पणियों में नोट किया गया है: * सीमा: सिंगल थ्रेडेड डिज़ाइन * देखें: aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf * बहु लड़ी पिरोया अनुप्रयोगों में लॉकिंग से जुड़ी समस्याओं के लिए
मार्टिन

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

c ++ 11 में या बाद में भी?
hg_git

5

जैसा कि अन्य ने उल्लेख किया है, एकल के लिए प्रमुख डाउनसाइड्स में उन्हें विस्तारित करने की अक्षमता शामिल है, और परीक्षण उद्देश्यों के लिए एक से अधिक उदाहरणों की तात्कालिकता के लिए शक्ति खोना, जैसे।

एकल के कुछ उपयोगी पहलू:

  1. आलसी या अपफ्रंट तात्कालिकता
  2. एक वस्तु के लिए आसान है जिसके लिए सेटअप और / या राज्य की आवश्यकता होती है

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

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


3

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

यदि आपने हर बार ऐसा किया है, तो प्रदर्शन बहुत कम हो जाएगा। एक सिंगलटन में इसका उपयोग करते हुए, आप उस हिट को एक बार लेते हैं और फिर बाद की सभी कॉलों को नहीं करना पड़ता है।


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

3

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

तो यहां तक ​​कि लॉगर या थ्रेड पूल के उदाहरण अमान्य हैं और उन्हें रणनीतियाँ द्वारा प्रतिस्थापित किया जाना चाहिए।


लॉगर को खुद सिंगल नहीं होना चाहिए। सामान्य "ब्रॉडकास्ट" मैसेजिंग सिस्टम होना चाहिए। लॉगर स्वयं प्रसारण संदेशों के ग्राहक हैं।
कैशॉक

थ्रेड-पूल भी सिंगल नहीं होना चाहिए। सामान्य सवाल यह है कि क्या आप कभी उनमें से एक से अधिक चाहते हैं? हाँ। जब मैंने आखिरी बार उनका उपयोग किया था तो हमारे पास एक आवेदन में 3 अलग-अलग थ्रेड-पूल थे।
कैशबैक

3

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


3

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



2

नीचे विध्वंसक में मेमोरी को निपटाने के साथ एक थ्रेड सेफ सिंगलटन पैटर्न को लागू करने के लिए बेहतर तरीका है। लेकिन मुझे लगता है कि विध्वंसक एक वैकल्पिक होना चाहिए क्योंकि कार्यक्रम समाप्त होने पर सिंगलटन का उदाहरण स्वचालित रूप से नष्ट हो जाएगा:

#include<iostream>
#include<mutex>

using namespace std;
std::mutex mtx;

class MySingleton{
private:
    static MySingleton * singletonInstance;
    MySingleton();
    ~MySingleton();
public:
    static MySingleton* GetInstance();
    MySingleton(const MySingleton&) = delete;
    const MySingleton& operator=(const MySingleton&) = delete;
    MySingleton(MySingleton&& other) noexcept = delete;
    MySingleton& operator=(MySingleton&& other) noexcept = delete;
};

MySingleton* MySingleton::singletonInstance = nullptr;
MySingleton::MySingleton(){ };
MySingleton::~MySingleton(){
    delete singletonInstance;
};

MySingleton* MySingleton::GetInstance(){
    if (singletonInstance == NULL){
        std::lock_guard<std::mutex> lock(mtx);
        if (singletonInstance == NULL)
            singletonInstance = new MySingleton();
    }
    return singletonInstance;
}

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


2
यह निश्चित रूप से बेहतर नहीं है। 1: आप सूचक का उपयोग करके स्वामित्व शब्दार्थ को परिभाषित नहीं कर रहे हैं। आपको C ++ में कभी भी पॉइंटर्स का उपयोग नहीं करना चाहिए जब तक कि आप उन्हें प्रबंधित करने के लिए तैयार न हों। 2: डबल चेकिंग लॉकिंग का आपका उपयोग पुरातन है और इसे करने के बहुत बेहतर आधुनिक तरीके हैं। 3: विनाश पर आपकी टिप्पणी भोली है। स्मृति की पुनर्स्थापना सफाई के बारे में विनाशकारी उपयोग की बात नहीं है। एक बेहतर संस्करण के लिए सुझाव: प्रश्न को देखें। वहाँ प्रस्तुत संस्करण पहले से ही बहुत बेहतर है।
मार्टिन यॉर्क

1

मैं एक साक्षात्कार परीक्षा के रूप में सिंगलटन का उपयोग करता हूं।

जब मैं किसी डेवलपर से कुछ डिज़ाइन पैटर्न के नाम पूछता हूं, अगर वे सभी का नाम सिंगलटन है, तो उन्हें काम पर नहीं रखा जाता है।


45
किराए पर लेने के बारे में कठिन और तेज नियम आपको संभावित कर्मचारियों की एक विस्तृत विविधता को याद करेंगे।
कार्ल १

13
बेवकूफों की एक विस्तृत विविधता मौजूद है। इसका मतलब यह नहीं है कि उन्हें काम पर रखने के लिए विचार किया जाना चाहिए। अगर कोई किसी भी डिजाइन पैटर्न का उल्लेख नहीं कर सकता है, तो मुझे लगता है कि वे किसी ऐसे व्यक्ति पर बेहतर होंगे जो सिंगलटन को जानता है, और कोई अन्य पैटर्न नहीं।
१५'०

3
रिकॉर्ड बुक के लिए - मेरी प्रतिक्रिया जीभ-इन-गाल थी। मेरी वास्तविक साक्षात्कार प्रक्रिया में, मैं यह आकलन करने की कोशिश करता हूं कि क्या हमें C ++ में किसी को ट्यूशन करने की आवश्यकता होगी, और यह कितना कठिन होगा। मेरे कुछ पसंदीदा उम्मीदवार ऐसे लोग हैं जो C ++ को अंदर-बाहर जानते हैं, लेकिन मैं उनके साथ इस बारे में शानदार बातचीत कर पाया।
क्रूज़ में मैट क्रूशांक

4
डाउन वोट। मेरे व्यक्तिगत अनुभव से - प्रोग्रामर किसी अन्य पैटर्न का नाम नहीं ले सकता है लेकिन सिंगलटन, लेकिन इसका मतलब यह नहीं है कि वह सिंग्लेटन्स का उपयोग करता है। व्यक्तिगत रूप से, मैं अपने कोड में सिंगलेट्स का उपयोग कर रहा था, इससे पहले कि मैंने कभी उनके बारे में सुना (मैंने उन्हें "स्मार्ट ग्लोबल्स" कहा - मुझे पता था कि वैश्विक क्या है)। जब मैंने उनके बारे में सीखा, जब मैंने उनके पेशेवरों और विपक्षों के बारे में सीखा - मैंने उनका उपयोग करना बंद कर दिया। अचानक, यूनिट परीक्षण मेरे लिए बहुत अधिक दिलचस्प हो गया जब मैं रुक गया ... क्या इससे मुझे एक बदतर प्रोग्रामर बना दिया गया? Pfff ...
पॉलियस

3
मैं "नाम कुछ डिज़ाइन पैटर्न" के लिए भी बकवास कर रहा हूँ। डिज़ाइनिंग यह समझने के बारे में है कि डिज़ाइन पैटर्न कैसे लागू किया जाए, न कि केवल उनके नामों को फिर से हटाने में सक्षम। ठीक है, कि एक नीचा नहीं वारंट हो सकता है लेकिन यह जवाब ट्रोल-ईश है।
कैशको

0

विरोधी उपयोग:

अत्यधिक सिंगलटन उपयोग के साथ एक बड़ी समस्या यह है कि पैटर्न आसान विस्तार और वैकल्पिक कार्यान्वयन की अदला-बदली को रोकता है। जहाँ भी सिंगलटन का उपयोग किया जाता है, क्लास-नाम हार्ड कोडित होता है।


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

मैंने उत्सुकता से आवर्ती टेम्पलेट पैटर्न का उपयोग करके विस्तार योग्य होने के लिए एक सिंगलटन के अपने संस्करण का निर्माण किया।
ज़ाचरी क्रूस

0

मुझे लगता है कि यह C # के लिए सबसे मजबूत संस्करण है:

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Same instance?
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 server requests
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // "Singleton"

  class LoadBalancer
  {
    private static LoadBalancer instance;
    private ArrayList servers = new ArrayList();

    private Random random = new Random();

    // Lock synchronization object
    private static object syncLock = new object();

    // Constructor (protected)
    protected LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      // Support multithreaded applications through
      // 'Double checked locking' pattern which (once
      // the instance exists) avoids locking each
      // time the method is invoked
      if (instance == null)
      {
        lock (syncLock)
        {
          if (instance == null)
          {
            instance = new LoadBalancer();
          }
        }
      }

      return instance;
    }

    // Simple, but effective random load balancer

    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

यहाँ .NET-अनुकूलित संस्करण है :

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{

  // MainApp test application

  class MainApp
  {

    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Confirm these are the same instance
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 requests for a server
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // Singleton

  sealed class LoadBalancer
  {
    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization
    private static readonly LoadBalancer instance =
      new LoadBalancer();

    private ArrayList servers = new ArrayList();
    private Random random = new Random();

    // Note: constructor is private.
    private LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      return instance;
    }

    // Simple, but effective load balancer
    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

आप इस पैटर्न को dotfactory.com पर पा सकते हैं ।


3
आप उन हिस्सों को अलग कर सकते हैं जो कोड को पढ़ने में आसान बनाने के लिए विशेष रूप से सिंग्लेटों के लिए निर्भर नहीं हैं।
मार्टिन यॉर्क

इसके अलावा, आपका पहला संस्करण संभव पढ़ने / लिखने के कारण थ्रेड-सुरक्षित नहीं है। देखें stackoverflow.com/questions/9666/…
थॉमस डेनकर

5
उह ... गलत भाषा? सवाल बहुत स्पष्ट रूप से C ++ का टैग है
देवसोलर

0

मेयर्स सिंगलटन पैटर्न ज्यादातर समय काफी अच्छी तरह से काम करता है, और अवसरों पर यह ऐसा करता है जो जरूरी नहीं कि कुछ भी बेहतर देखने के लिए भुगतान करता है। जब तक कंस्ट्रक्टर कभी भी फेंक नहीं देगा और सिंगललेट्स के बीच निर्भरता नहीं होगी।

एक सिंगलटन विश्व स्तर पर सुलभ वस्तु (अब से गाओ) के लिए एक कार्यान्वयन है, हालांकि सभी गाओ एकल नहीं हैं।

लॉगर स्वयं को एकल नहीं होना चाहिए, लेकिन लॉग करने का साधन आदर्श रूप से विश्व स्तर पर पहुंच योग्य होना चाहिए, यह निर्धारित करने के लिए कि लॉग संदेश कहां से उत्पन्न हो रहा है या यह कैसे लॉग हो जाता है।

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

इसे ध्यान में रखते हुए, GOAs को इस तरह से आरंभ किया जा सकता है:

namespace {

T1 * pt1 = NULL;
T2 * pt2 = NULL;
T3 * pt3 = NULL;
T4 * pt4 = NULL;

}

int main( int argc, char* argv[])
{
   T1 t1(args1);
   T2 t2(args2);
   T3 t3(args3);
   T4 t4(args4);

   pt1 = &t1;
   pt2 = &t2;
   pt3 = &t3;
   pt4 = &t4;

   dostuff();

}

T1& getT1()
{
   return *pt1;
}

T2& getT2()
{
   return *pt2;
}

T3& getT3()
{
  return *pt3;
}

T4& getT4()
{
  return *pt4;
}

इसे उतने ही सूक्ष्मता से करने की आवश्यकता नहीं है, और स्पष्ट रूप से भरी हुई लाइब्रेरी में ऐसी वस्तुएं हैं जिनमें आप शायद अपने जीवनकाल को प्रबंधित करने के लिए कुछ अन्य तंत्र चाहते हैं। (उन्हें एक वस्तु में रखो जो आपको पुस्तकालय को लोड करने पर मिलती है)।

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


0

मुझे अभी भी नहीं पता है कि एक सिंगलटन को वैश्विक क्यों होना चाहिए।

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

मैं यह नहीं देखता कि यह कार्यक्षमता खराब क्यों होगी।


मुझे समझ में नहीं आता कि आपको क्यों लगता है कि यह एक वैश्विक होना है।
मार्टिन

इस सूत्र के अनुसार, हर कोई कह रहा था कि एक गायक को वैश्विक होना चाहिए
ज़ाचरी क्रूस

1
नहीं। सूत्र बताता है कि एक सिंगलटन के पास वैश्विक स्थिति है। ऐसा नहीं है कि यह एक वैश्विक चर है। आपके द्वारा प्रस्तावित समाधान में वैश्विक स्थिति है। आपके द्वारा प्रस्तावित समाधान भी एक वैश्विक चर का उपयोग कर रहा है; एक वर्ग का एक स्थिर सदस्य "स्टेटिक स्टोरेज ड्यूरेशन" का एक ऑब्जेक्ट है एक वैश्विक चर "स्टेटिक स्टोरेज अवधि" का एक ऑब्जेक्ट है। इस प्रकार दो मूल रूप से थोड़े अलग शब्दार्थ / स्कोप के साथ एक ही बात है।
मार्टिन

तो "स्थैतिक भंडारण अवधि" के कारण एक निजी स्थिर चर अभी भी वैश्विक है?
जाकारी क्राउस

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

0

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

मुझे यकीन है कि अन्य समाधान भी हैं, लेकिन मुझे यह बहुत उपयोगी और लागू करने में आसान लगता है।


0

यदि आप सिंगलटन बनाने वाले हैं और इसका उपयोग करने वाले हैं, तो इसे सिंगलटन के रूप में न बनाएँ (इसका कोई अर्थ नहीं है क्योंकि आप इसे सिंगलटन बनाए बिना ऑब्जेक्ट की विलक्षणता को नियंत्रित कर सकते हैं) लेकिन यह तब समझ में आता है जब आप किसी डेवलपर के लाइब्रेरी और आप अपने उपयोगकर्ताओं को केवल एक ही वस्तु की आपूर्ति करना चाहते हैं (इस मामले में आप सिंगलटन को बनाने वाले हैं, लेकिन आप उपयोगकर्ता नहीं हैं)।

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


-1

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

संपादित करें - निश्चित रूप से इन्हें केवल पढ़ा जाना चाहिए!


लेकिन यह सवाल भीख माँग रहा है; क्यों उपयोगकर्ता भाषा और मदद फ़ाइल के लिए पथ उदाहरणों तरीका हो की क्या ज़रूरत है सब पर ?
DrPizza

2
हमारे पास इसके लिए ग्लोबल्स हैं। वहाँ उन्हें एकल बनाने की कोई जरूरत नहीं है
jalf

वैश्विक चर - फिर आप उन्हें रजिस्ट्री / डेटाबेस से कैसे अनुक्रमित करेंगे? गोबल वर्ग - फिर आप कैसे सुनिश्चित करते हैं कि उनमें से केवल एक ही है?
मार्टिन बेकेट

@ एमजीबी: आप उन्हें रजिस्ट्री / डेटाबेस से मूल्यों को पढ़कर और उन्हें वैश्विक चर में संग्रहीत करके क्रमबद्ध करते हैं (यह संभवतः आपके मुख्य कार्य के शीर्ष पर किया जाना चाहिए)। आप यह सुनिश्चित करते हैं कि वर्ग की केवल एक ही वस्तु है, केवल कक्षा की एक वस्तु बनाकर ... वास्तव में ... यह मुश्किल है कि 'grep -rn "new \ + global_class_name"।' ? वास्तव में?
पॉलियस

7
@ एमबी: पृथ्वी पर मैं यह क्यों सुनिश्चित करूंगा कि केवल एक ही है? मुझे बस यह जानना चाहिए कि एक उदाहरण हमेशा वर्तमान सेटिंग्स का प्रतिनिधित्व करता है । लेकिन कोई कारण नहीं है कि मुझे जगह के आसपास अन्य सेटिंग्स ऑब्जेक्ट्स की अनुमति नहीं दी जानी चाहिए। उदाहरण के लिए, "उपयोगकर्ता वर्तमान में परिभाषित कर रहा है, लेकिन अभी तक लागू नहीं हुआ है" के लिए शायद एक। या "पहले से सहेजे गए कॉन्फ़िगरेशन को कॉन्फ़िगर करता है ताकि वह बाद में उनके पास वापस आ सके"। या आपके प्रत्येक यूनिट परीक्षण के लिए एक।
१२:१२

-1

एक और कार्यान्वयन

class Singleton
{
public:
    static Singleton& Instance()
    {
        // lazy initialize
        if (instance_ == NULL) instance_ = new Singleton();

        return *instance_;
    }

private:
    Singleton() {};

    static Singleton *instance_;
};

3
यह वास्तव में भयानक है। देखें: एक बेहतर आलसी आरंभीकरण के लिए stackoverflow.com/questions/1008019/c-singleton-design-pattern/… और अधिक महत्वपूर्ण रूप से गारंटी निर्धारक विनाश।
मार्टिन यॉर्क

यदि आप पॉइंटर्स का उपयोग करने जा रहे हैं, तो Instance()एक पॉइंटर लौटना चाहिए, न कि एक संदर्भ। अपनी .cppफ़ाइल के अंदर , उदाहरण को अशक्त करने के लिए आरंभ करें Singleton* Singleton::instance_ = nullptr;:। और Instance()के रूप में लागू किया जाना चाहिए: if (instance_ == nullptr) instance_ = new Singleton(); return instance_;
डेनिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.