2011-01-16 20 views
8

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

private static final ClassName INSTANCE = new ClassName(); 

public static ClassName getInstance() { 
    return INSTANCE; 
} 

नमूना 2:

private static class SingletonHolder { 
    public static final ClassName INSTANCE = new ClassName(); 
} 

public static ClassName getInstance() { 
    return SingletonHolder.INSTANCE; 
} 

नमूना 3:

private static ClassName INSTANCE; 

public static synchronized ClassName getInstance() 
{ 
    if (INSTANCE == null) 
     INSTANCE = new ClassName(); 

    return INSTANCE; 
} 

परियोजना मैं एटीएम का उपयोग कर रहा हर जगह नमूना 2 का उपयोग करता है, लेकिन मैं एक तरह से नमूना की तरह 3 और। एनम संस्करण भी है, लेकिन मुझे बस यह नहीं मिला।

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

उत्तर

18

जावा में एक सिंगलटन लागू करने के लिए सबसे सुरक्षित और आसान तरीका enums का उपयोग कर (आप की तरह उल्लेख किया) के द्वारा होता है:

public enum ClassName { 
    INSTANCE; 

    // fields, setters and getters 
} 

enum अर्थ विज्ञान गारंटी देता है कि वहाँ केवल एक ही INSTANCE

तो नहीं होगा एनम दृष्टिकोण का उपयोग करके, आपको दौड़ की स्थिति और प्रतिबिंब जैसे कई पहलुओं का ख्याल रखना चाहिए। मैं कुछ ढांचे के सिंगलेट्स तोड़ रहा हूं, और उनका दुरुपयोग कर रहा हूं, क्योंकि वे ठीक से लिखे गए नहीं थे। Enum गारंटी देता है कि कोई भी इसे तोड़ देगा।

+0

लेकिन मैं इसका उपयोग कैसे करूं? उदाहरण के लिए, मेरे पास यह है: सार्वजनिक वर्ग MyClass { सार्वजनिक enum क्लासनाम { इंस्टेंस; // क्या मैं इसके बजाय यहां अपने सभी तरीकों को डालता हूं ... } // जैसा कि मैं सामान्य रूप से करता हूं? } संपादित करें: अरे, टिप्पणियों पर कोई स्वरूपण नहीं है ?? घृणा करता हूं! – jurchiks

+1

आप नीचे अपना सिंगलटन फ़ील्ड और विधियां लिखते हैं। और फिर उन्हें 'ClassName.INSTANCE.doSomething (foo)' – Bozho

+0

@jurchiks: yes के माध्यम से एक्सेस करें। अन्यत्र, आप सिंगलटन विधियों का उपयोग करने के लिए 'ClassName.INSTANCE.methodName()' को कॉल करेंगे (या शायद 'ClassName.INSTANCE.') से छुटकारा पाने के लिए स्थिर आयात का उपयोग करें। – Carl

1

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

2

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

इस प्रकार, चाहे आप सिंगलटन (यदि बिल्कुल) प्राप्त करते हैं, इस बात पर ध्यान दिए बिना, इस वर्ग को आपके ऑब्जेक्ट तक पहुंचने के तरीके को बदलने पर विचार करें। हालांकि इसका मतलब है कि रचनाकारों को संशोधित करना और "वितरण परिवर्तन" को बदलना, मुझे पता चला है कि निर्भरता इंजेक्शन ढांचे लागत को कम करते हैं। डी ढांचा भी तब सिंगलटन तत्कालता का ख्याल रख सकता है (उदाहरण के लिए, गुइस ऐसा करता है)।

इसके अलावा। विकल्प 3 सामान्य और सबसे आम (और धागा सुरक्षित) संस्करण है जिसे मैं परिचित हूं। विकल्प 1 ज्यादातर गैर आलसी प्रारंभिक (हमेशा स्वीकार्य नहीं) के लिए है। मैंने 2 बार कभी नहीं देखा है।

+0

खैर, जिस वर्ग को मैं तत्काल करना चाहता हूं, जिसमें संभवतः बहुत सारे डेटा के साथ 2 मानचित्र ऑब्जेक्ट्स हैं, प्रत्येक मानचित्र के लिए दो विधियों को कुंजी का उपयोग करके मूल्य प्राप्त करने के लिए (और यदि यह शून्य है तो मूल्य को पॉप्युलेट करें) और डेटाबेस तक पहुंचने वाली दो विधियां (पहले पॉप्युलेट करने के लिए किसी चयनित कुंजी का मान, मौजूदा डेटा का उपयोग कर डेटाबेस से डेटा डालने/अपडेट/हटाने के लिए दूसरा)। यहां गेटर्स/सेटर्स की गिनती नहीं है। क्या आपको लगता है कि यह सिंगलटन नहीं होना चाहिए? – jurchiks

+0

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

+0

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

4

नमूना 1 आलसी प्रारंभिकता का उपयोग नहीं करता है।

नमूना 2 और 3 दोनों आलसी हैं। नमूना 2 Initialization on demand holder idiom (IODH) का उपयोग करता है जिसमें कोई सिंक्रनाइज़ेशन ओवरहेड है। इसलिए यह नमूना 3.

प्रभावी जावा में (आइटम 3) की तुलना में तेजी है, यहोशू बलोच सिफारिश की है कि एक एकल तत्व enum प्रकार एक सिंगलटन लागू करने के लिए सबसे अच्छा तरीका है।

हालांकि, अगर आप enum प्रकार के बारे में अनिश्चित हैं, तो IODH के साथ चिपके रहें।

+0

क्यों नमूना 1 आलसी प्रारंभिक उपयोग नहीं करता है? मुझे लगता है कि यह उपयोग कर रहा है क्योंकि केवल एक उदाहरण है, और एक प्रारंभिकरण किया जाता है। – Sam003

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