आपको स्टैटिक क्लास के बजाय सिंगलटन पैटर्न का उपयोग कब करना चाहिए? [बन्द है]


85

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


एक जावा वर्ग तब तक स्थिर नहीं हो सकता जब तक कि उसका आंतरिक वर्ग
हर्षा

1
यदि वस्तु की स्थिति मायने रखती है, तो सिंगलटन का उपयोग करें, अन्यथा, एक स्थिर वर्ग का उपयोग करें।
लेवेंट डिविलीग्लू

जवाबों:


80
  • एकल वर्ग इंटरफेस को लागू कर सकते हैं और अन्य वर्गों से विरासत में प्राप्त कर सकते हैं।
  • सिंगलटन को आलसी लोड किया जा सकता है। केवल जब यह वास्तव में जरूरत है। यह बहुत ही आसान है यदि आरंभिक में महंगे संसाधन लोडिंग या डेटाबेस कनेक्शन शामिल हैं।
  • सिंगलटेन्स एक वास्तविक वस्तु प्रदान करते हैं।
  • सिंगलेट्स को फैक्ट्री में बढ़ाया जा सकता है। पर्दे के पीछे वस्तु प्रबंधन अमूर्त है, इसलिए यह बेहतर रखरखाव योग्य है और बेहतर कोड में परिणाम है।

2
इस लिंक को भी देख लें: codeofdoom.com/wordpress/2008/04/20/…
अमित

4
"सिंगलेट्स को आलसी लोड किया जा सकता है" - सी # में, स्थिर निर्माणकर्ता को केवल पहली बार एक स्थिर सदस्य को संदर्भित किया जाता है। PHP में, आप ऑटोलडिंग का उपयोग केवल तभी कर सकते हैं जब उसने पहली बार क्लास का उपयोग किया हो।
मप्रेन

जावा स्टैटिक इनिशियलाइज़ेशन आलसी होने के साथ-साथ आलसी भी हैं। वहाँ सिंग्लेटन्स के लिए कोई अंक नहीं।
मीकफ़े

13

कैसे "दोनों से बचें" के बारे में? एकल और स्थिर वर्ग:

  • वैश्विक स्थिति का परिचय दे सकते हैं
  • कसकर कई अन्य वर्गों के लिए युग्मित हो जाओ
  • निर्भरता छिपाएं
  • अलगाव में इकाई परीक्षण कक्षाएं कठिन बना सकती हैं

इसके बजाय, नियंत्रण कंटेनर पुस्तकालयों की निर्भरता इंजेक्शन और व्युत्क्रम में देखें । आईओसी के कई पुस्तकालय आपके लिए आजीवन प्रबंधन का काम संभालेंगे।

(हमेशा की तरह, अपवाद हैं, जैसे स्थैतिक गणित कक्षाएं और C # विस्तार विधियाँ।)


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

@ LCDleary - सहमत; हालांकि क्लासिक कार्यान्वयन अक्सर कोडबेल में सिंग्लटन.गेट इनस्टेंस () को छोड़ देता है। संसाधनों, कैश आदि का प्रबंधन करने के लिए "सिंगलटन" को POCO / POJO और IoC कंटेनर फ्रेमवर्क के साथ कार्यान्वित किया जा सकता है जो आजीवन प्रबंधन का समर्थन करते हैं (कंटेनर के जीवनकाल के प्रकार को पंजीकृत करें और प्रत्येक संकल्प को एक ही उदाहरण मिलेगा)।
ट्रूविल

9
यदि आप अपने सिंगलेट्स को उचित दफन देना चाहते हैं, तो singletonfuneralervice.com पर जाएं
TrueWill

1
Hide Dependenciesइस बिंदु पर थोड़ा साइडइन्फो: आप निन्यूज का उपयोग करके उदाहरण के लिए नियंत्रण पैटर्न के व्युत्क्रम को लागू कर सकते हैं । यह आपको केवल एक प्रकार के एक उदाहरण का उपयोग करके इसे बाध्य करने की अनुमति देता है SingletonScope, जिसका अर्थ है कि यह उसी उदाहरण को इंजेक्ट करेगा , लेकिन वर्ग सिंगलटन नहीं होगा।
लकीलीके

8

मेरा तर्क है कि केवल अंतर सिंटैक्स है: MySingleton.Current.Whatever () बनाम MySingleton.Whatever ()। डेविड ने कहा कि राज्य, दोनों मामलों में अंततः "स्थिर" है।


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


7

इस मुद्दे के बारे में मेरी पसंदीदा चर्चाओं में से एक यहाँ है (मूल साइट डाउन, जिसे अब इंटरनेट आर्काइव वेबैक मशीन से जोड़ा गया है ।)

एक सिंगलटन के लचीलेपन लाभ को संक्षेप में प्रस्तुत करने के लिए:

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

5

स्थिर चर के भार के साथ एक स्थिर वर्ग एक हैक का एक सा है।

/**
 * Grotty static semaphore
 **/
 public static class Ugly {

   private static int count;

   public synchronized static void increment(){
        count++;
   }

   public synchronized static void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized static boolean isClear(){
         return count==0;    

    }
   }

वास्तविक उदाहरण के साथ एक सिंगलटन बेहतर है।

/**
 * Grotty static semaphore
 **/
 public static class LessUgly {
   private static LessUgly instance;

   private int count;

   private LessUgly(){
   }

   public static synchronized getInstance(){
     if( instance==null){
        instance = new LessUgly();
     }
     return instance;
   }
   public synchronized void increment(){
        count++;
   }

   public synchronized void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized boolean isClear(){
         return count==0;    

    }
   }

राज्य केवल उदाहरण में है।

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

public static class LessUgly {
       private static Hashtable<String,LessUgly> session;
       private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
       private static final POOL_SIZE=5;
       private int count;

       private LessUgly(){
       }

       public static synchronized getInstance(){
         if( session==null){
            session = new Hashtable<String,LessUgly>(POOL_SIZE);
            for( int i=0; i < POOL_SIZE; i++){
               LessUgly instance = new LessUgly();  
               freePool.add( instance)
            }
         }
         LessUgly instance = session.get( Session.getSessionID());
         if( instance == null){
            instance = freePool.read();
         }
         if( instance==null){
             // TODO search sessions for expired ones. Return spares to the freePool. 
             //FIXME took too long to write example in blog editor.
         }
         return instance;
       }     

एक स्थिर वर्ग के साथ कुछ ऐसा ही करना संभव है लेकिन अप्रत्यक्ष प्रेषण में प्रति कॉल ओवरहेड होगा।

आप उदाहरण प्राप्त कर सकते हैं और इसे एक तर्क के रूप में फ़ंक्शन में पास कर सकते हैं। इससे कोड को "सही" सिंगलटन पर निर्देशित किया जा सकता है। हम जानते हैं कि आपको केवल इसकी आवश्यकता होगी ... जब तक आप नहीं करते।

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


4

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

ObjectFactory.getInstance().makeObject();

ऑब्जेक्ट फैक्ट्री एक ऐसी वस्तु है जो एक विशिष्ट सेवा करती है।

इसके विपरीत, स्थिर तरीकों से भरा एक वर्ग क्रियाओं का एक संग्रह है जिसे आप संबंधित समूह (कक्षा) में आयोजित करना चाहते हैं। उदाहरण के लिए

StringUtils.reverseString("Hello");
StringUtils.concat("Hello", "World");

StringUtils उदाहरण यहाँ कार्यक्षमता का एक संग्रह है जिसे कहीं भी लागू किया जा सकता है। सिंगलटन फैक्ट्री ऑब्जेक्ट एक विशिष्ट प्रकार की वस्तु है जिसमें एक स्पष्ट जिम्मेदारी होती है जिसे आवश्यक बनाया और पास किया जा सकता है।


4

स्थैतिक कक्षाओं को रनटाइम पर त्वरित किया जाता है। यह समय लेने वाला हो सकता है। जरूरत पड़ने पर ही सिंग्लेटों को त्वरित किया जा सकता है।


13
एकल भी रनटाइम पर त्वरित कर रहे हैं ...
पुनरावर्ती

1
@recursive: सिंगलटन इंस्टेंटेशन को नियंत्रित किया जा सकता है।
निकित बटाले

3
शायद एक बेहतर शब्द आरंभीकरण होगा (तात्कालिकता के बजाय)
मार्लोन

3

एकल वर्गों को उसी तरह से इस्तेमाल नहीं किया जाना चाहिए जैसे कि स्थिर वर्ग। सार में,

MyStaticClass.GetInstance().DoSomething();

अनिवार्य रूप से के रूप में ही है

MyStaticClass.DoSomething();

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

var svc = new MyComplexServce(MyStaticClass.GetInstance());

सेवा को यह पता नहीं होना चाहिए कि वस्तु एक सिंगलटन है, और वस्तु को सिर्फ एक वस्तु के रूप में मानना ​​चाहिए।

ऑब्जेक्ट को निश्चित रूप से कार्यान्वित किया जा सकता है, कार्यान्वयन विवरण के रूप में और समग्र कॉन्फ़िगरेशन के एक पहलू के रूप में, एक सिंगलटन के रूप में अगर यह चीजों को आसान बनाता है। लेकिन ऑब्जेक्ट का उपयोग करने वाली चीजों को यह जानना नहीं चाहिए कि ऑब्जेक्ट एक सिंगलटन है या नहीं।


2

यदि "स्टैटिक क्लास" से आपका तात्पर्य एक ऐसे वर्ग से है जिसमें केवल स्थिर वैरिएबल हैं, तो वे वास्तव में राज्य बनाए रख सकते हैं। मेरी समझ यह है कि अंतर केवल यह होगा कि आप इस चीज़ तक कैसे पहुँचते हैं। उदाहरण के लिए:

MySingleton().getInstance().doSomething();

बनाम

MySingleton.doSomething();

MySingleton के इंटर्नल स्पष्ट रूप से उन दोनों के बीच अलग होंगे, लेकिन थ्रेड-सेफ्टी के मुद्दे अलग-अलग हैं, वे दोनों क्लाइंट कोड के संबंध में समान प्रदर्शन करेंगे।


2
सिंगलटन स्वयं वस्तु हैं -> उन्हें तर्क के रूप में पारित किया जा सकता है।
क्रिश्चियन क्लॉसर

2

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


1

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

एक सिंगलटन के बहुत अधिक उदाहरण से पता चलता है कि यह कैसे नहीं करना है।


4
हार्डवेयर संसाधनों को नियंत्रित करने वाले प्रबंधक वर्गों के बारे में क्या? लॉग फ़ाइल कक्षाओं के बारे में क्या?
RJFalconer

0

यदि एक सिंगलटन ऐसी चीज है जिसे आप निपटाने के लिए, उसके बाद साफ करने के लिए, आप इस पर विचार कर सकते हैं जब यह एक सीमित संसाधन है (यानी इसका केवल 1) जो आपको हर समय की आवश्यकता नहीं है, और किसी प्रकार की स्मृति है या आवंटित होने पर संसाधन की लागत।

जब आपके पास एक सिंगलटन होता है, तो स्टेटिक स्टेट फ़ील्ड वाले स्थिर वर्ग के विपरीत क्लीनअप कोड अधिक स्वाभाविक लगता है।

हालाँकि, कोड एक ही तरह का दिखाई देगा, यदि आपके पास पूछने के लिए अधिक विशिष्ट कारण हैं, तो शायद आपको विस्तृत जानकारी देनी चाहिए।


0

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

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


0

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


0

स्टेटिक कक्षाओं को तर्कों के रूप में पारित नहीं किया जा सकता है; एक सिंगलटन के उदाहरण हो सकते हैं। जैसा कि अन्य उत्तरों में बताया गया है, स्थैतिक कक्षाओं के साथ मुद्दों को फैलाने के लिए देखें।

आरपी


0

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

एक बार एक सिंगलटन ऑब्जेक्ट का संदर्भ प्राप्त होने के बाद, इसे किसी अन्य ऑब्जेक्ट की तरह ही उपयोग किया जा सकता है। क्लाइंट कोड को सिंगलटन का उपयोग करने की आवश्यकता नहीं है, अगर सिंगलटन का संदर्भ पहले से संग्रहीत है:

Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

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


0

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


0

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


0

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


0

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

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

हालाँकि, सिंग्लटन का निर्माण कुछ स्थिर चर के साथ किया जा सकता है, आप इसकी तुलना 'गोटो' से कर सकते हैं। यह अन्य संरचनाओं के निर्माण के लिए उपयोगी हो सकता है, लेकिन आपको वास्तव में यह जानने की आवश्यकता है कि इसका उपयोग कैसे करना चाहिए और इसे 'अति प्रयोग' नहीं करना चाहिए। इसलिए सामान्य अनुशंसा है कि आप सिंगलटन से चिपके रहें, और स्थिर का उपयोग करें।

अन्य पोस्ट की भी जाँच करें: एक एकल कार्यान्वयन पर एक स्थिर वर्ग का चयन क्यों करें?


0

उल्लेख इस

सारांश:

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

ख। एक सिंगलटन का उपयोग करें यदि यह एक विशेष रूप से "भारी" वस्तु है। यदि आपकी ऑब्जेक्ट बड़ी है और उचित मात्रा में मेमोरी, बहुत सारे n / w कॉल (कनेक्शन पूल) ..etc लेती है। यह सुनिश्चित करने के लिए कि इसका कई बार तात्कालिक होना नहीं है। एक सिंगलटन वर्ग इस तरह के मामले को रोकने में मदद करेगा


-1

जब एकल वर्ग को राज्य की आवश्यकता होती है। सिंगलटन एक वैश्विक स्थिति बनाए रखते हैं, स्थिर वर्ग ऐसा नहीं करते हैं।

उदाहरण के लिए, एक रजिस्ट्री वर्ग के आसपास एक सहायक बनाना: यदि आपके पास परिवर्तनशील छत्ता (HKey चालू उपयोगकर्ता बनाम HKEY स्थानीय मशीन) है तो आप जा सकते हैं:

RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine

अब उस सिंगलटन को कोई और कॉल लोकल मशीन हाइव पर काम करेगा। अन्यथा, एक स्थिर वर्ग का उपयोग करते हुए, आपको यह बताना होगा कि लोकल मशीन हाइवेमेट को हाइव करती है, या जैसी विधि है ReadSubkeyFromLocalMachine


1
मैं इस तरह से एक सिंगलटन का उपयोग करने के खिलाफ तर्क दूंगा ... राज्यों को सुस्त रखना बहुत खतरनाक है, क्योंकि अगला कॉलर हाइव सेट करना भूल सकता है, और रजिस्ट्री को गलत हाइव में लिख सकता है ... :-( यह है) शायद दुरुपयोग का एक उदाहरण है जो लोगों को लगता है कि सिंग्लेटन्स खराब हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.