कंस्ट्रक्टर का उपयोग कब करें और गेटइनस्टांस () विधि (स्टैटिक फैक्ट्री मेथड) का उपयोग कब करें?


84
  1. हमें कब और कैसे एक कंस्ट्रक्टर का उपयोग करना चाहिए

    Foo bar = new Foo();
    
  2. और कब और कैसे हमें getInstance () का उपयोग करना चाहिए (स्थैतिक कारखाने के तरीके)

    Foo bar = Foo.getInstance();
    

इन दोनों के बीच क्या अंतर है? मैंने हमेशा एक कंस्ट्रक्टर का उपयोग किया है, लेकिन मुझे getInstance()इसके बजाय कब उपयोग करना चाहिए ?


क्या आप स्वयं कक्षा लिख ​​रहे हैं? यदि नहीं, तो आप क्या कह रहे हैं जो इसे प्रदान करता है?
क्रिस बी।

इसलिए, कक्षा के कार्यान्वयन का मतलब है कि मैं सिंगलटन पैटर्न लागू कर रहा हूं, है ना?
ज़ूल

आप कर रहे हैं बुला getInstance() , या आप कर रहे हैं एक विधि लेखन कहा जाता है getInstance()?
क्रिस बी।

1
यदि प्रश्न कंस्ट्रक्टर बनाम स्टेटिक फ़ैक्टरी विधियों के बारे में है , तो मैं स्पष्ट करने और शीर्षक बदलने का सुझाव देता हूं।
पास्कल थिवेंट

@zengr: आपके अपडेट 2 के विषय में, यह इसलिए हो सकता है क्योंकि आपने अपनी स्थैतिक विधि का नाम सम्मेलन के अनुसार नहीं रखा था, जो यह तय करती है कि इसे नाम दिया जाना चाहिए Foo.newInstance()Foo.getInstance()एक वर्ग के एकल उदाहरण प्राप्त करने के लिए एक सम्मेलन है। आपको अपने उदाहरण को सही करना चाहिए और Foo.newInstance()इसके बजाय उपयोग करना चाहिए।
JRL

जवाबों:


96

हर कोई एकल पर ध्यान केंद्रित करने लगता है जबकि मुझे लगता है कि प्रश्न वास्तव में कंस्ट्रक्टर बनाम स्टेटिक फैक्ट्री विधियों के बारे में है

यह वास्तव में आइटम 1 है: जोशुआ बलोच द्वारा प्रभावी जावा के निर्माणकर्ताओं के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें :

आइटम 1: कंस्ट्रक्टरों के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें

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

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

ध्यान दें कि एक स्टैटिक फैक्ट्री विधि डिज़ाइन पैटर्न [ फैक्टरी गामा 95, पी] से फैक्ट्री मेथड पैटर्न के समान नहीं है । 107]। इस मद में वर्णित स्थिर कारखाना विधि का डिज़ाइन पैटर्न में कोई सीधा समकक्ष नहीं है ।

एक वर्ग अपने ग्राहकों को निर्माणकर्ताओं के बजाय या उसके अलावा स्थैतिक कारखाना विधियों के साथ प्रदान कर सकता है। सार्वजनिक निर्माता के बजाय एक स्थिर कारखाना विधि प्रदान करने के फायदे और नुकसान दोनों हैं।

लाभ (पुस्तक उद्धृत):

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

नुकसान (अभी भी पुस्तक उद्धृत):

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

8
पिछले कुछ को कम किया जा सकता है। जब मैं फ़ैक्टरी विधियाँ बनाता हूँ तो इसे बनाने के लिए मुझे फैक्ट्री में एक स्थिर आंतरिक वर्ग और फैक्ट्री में विभिन्न नए इनस्टेंस तरीके मिलते हैं। इसने मुझे अतीत में समय के आसपास शिकार करने से बचाया है। :)
रिच शूलर

@ क्यूबर्टिकस कारखाने के तरीकों के लिए समर्पित आंतरिक वर्ग एक अच्छा विचार है। मैं इसे कोशिश करूँगा, thx
डेव ओ।

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

9

आपको दो प्रश्न मिले हैं: मुझे कब एक विधि को कॉल करना चाहिए getInstance(), और मुझे कब बनाना चाहिए ?

यदि आप एक getInstance()विधि को कॉल करने का निर्णय ले रहे हैं , तो यह आसान है। आपको यह पता करने के लिए कि आपको कब कॉल करना चाहिए, बस आपको क्लास के डॉक्यूमेंटेशन को पढ़ना होगा। उदाहरण के लिए, NumberFormatएक निर्माता और एक getInstance()विधि प्रदान करता है ; getInstance()विधि आप दे देंगे एक स्थानीय NumberFormat। के लिए Calendar, दूसरे हाथ पर, निर्माता सुरक्षित है। आप है कॉल करने के लिए getInstance()प्राप्त करने के लिए।

यदि आप यह तय कर रहे हैं कि क्याgetInstance() विधि बनानी है , तो आपको यह तय करना होगा कि आप क्या करने की कोशिश कर रहे हैं। या तो आप नहीं चाहते कि लोग आपके कंस्ट्रक्टर को कॉल करें (आप एक सिंगलटन या फैक्ट्री बना रहे हैं ), या आपको कोई आपत्ति नहीं है (जैसा कि NumberFormatऊपर, जहां वे कॉलर की सुविधा के लिए कुछ ऑब्जेक्ट्स को इनिशियलाइज़ कर रहे हैं)।


कहानी संक्षिप्त में? getInstance()अपने स्वयं के कोड में तरीके बनाने के बारे में चिंता न करें । यदि समय आता है जब वे उपयोगी होंगे, तो आपको पता चल जाएगा। और सामान्य तौर पर, यदि आप एक क्लास के कंस्ट्रक्टर को कॉल कर सकते हैं , तो आप शायद ऐसा करने वाले हैं, भले ही क्लास एक getInstance()विधि प्रदान करता हो ।


7

GetInstance विधियों के लिए उपयोग:

  • यदि आप निर्माण को नियंत्रित / प्रतिबंधित करना चाहते हैं जैसे सिंग्लटन
  • फैक्ट्री पैटर्न लागू करें, जैसे DriverManager.getConnection
  • आप कैसे उदाहरण का निर्माण किया है के रूप में बेहतर नाम प्रदान करना चाहते हैं (कंस्ट्रक्टर्स वर्ग के नाम के रूप में एक ही नाम होना आवश्यक है), चेकआउट NumberFormat कारखाने तरीकों getCurrencyInstance , getIntegerInstance और इसके उदाहरण के रूप में दूसरों।

लेकिन अधिकांश समय आपकी वस्तु एक साधारण POJO होगी और सार्वजनिक निर्माणकर्ताओं का उपयोग सबसे व्यावहारिक और स्पष्ट समाधान है।

U1: getInstance दूसरी कक्षा से

एक अलग वर्ग का एक उदाहरण लौटाने के लिए:

public class FooFactory {
    public static Foo getInstance() {
        return new Foo();
    }
}

NumberFormat.getInstanceविधियाँ ऐसा करती हैं क्योंकि वे वास्तव में उदाहरण देते हैं DecimalFormat

U2: सिंगलटन समस्याएं

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


फैक्ट्री पैटर्न के मामले में 'createInstance' या 'buildInstance' जैसे किसी अन्य विधि का नाम बहुत बेहतर होगा, लेकिन फिर भी पूछनेवाला का एक संभावित मामला क्या हो सकता है (मेरे लिए अभी भी थोड़ा नीच और कुछ होमवर्क जैसा लगता है)
jadehaan

6

यदि आप दोनों का उपयोग कर सकते हैं तो यह एक खराब कार्यान्वित सिंगलटन पैटर्न की तरह लगता है

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

कक्षा की कई वस्तुओं के निर्माण की अनुमति देने के लिए पहले का उपयोग करें।

लेकिन अपनी कक्षा को दोनों संभावनाएँ न दें।

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


अपडेट किया गया सवाल, थोड़ा भ्रमित करने वाला था, क्षमा करें
zengr

4
------> "ध्यान रखें कि अधिक
सिंगनेट्स का

1

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


0

सिंगलटन दुष्ट हैं। जिन समस्याओं को मैंने अपने आस-पास देखा है, वे किसी सिस्टम के पुन: उपयोग या विस्तार की क्षमता के बारे में नहीं हैं (हालांकि मैं देख सकता हूं कि ऐसा कैसे हो सकता है), और अधिक ताकि मैं उस समय की संख्या की गणना नहीं कर पाऊं जिसे मैंने अस्पष्ट बग में देखा है प्रणाली जो एकल से उत्पन्न होती है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.