क्या सिंगलटन के लिए वैकल्पिक है


114

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

सिंगलटन के बिना, हमें अपने कोड में हर जगह के उदाहरण को पास करना होगा। यह इतना गड़बड़ हो रहा है इसलिए हमने एक सिंगलटन रैपर लिखा है। अब हम उसी कोड को PHP और .NET में पोर्ट कर रहे हैं, मैं सोच रहा हूं कि क्या कोई बेहतर पैटर्न है जिसे हम कॉन्फ़िगरेशन ऑब्जेक्ट के लिए उपयोग कर सकते हैं।

जवाबों:


131

Google परीक्षा ब्लॉग (क्रम परीक्षण योग्य कोड बनाने के लिए) सिंगलटन बचने के बारे में प्रविष्टियों की एक श्रृंखला है। शायद यह आपकी मदद कर सकता है:

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

संक्षेप में, हम सभी नए ऑपरेटरों को एक कारखाने में स्थानांतरित करते हैं। हम एक ही कारखाने में समान जीवनकाल की सभी वस्तुओं का समूह बनाते हैं।


3
*** एकल गाने से बचने के लिए निर्भरता इंजेक्शन का उपयोग
जस्टिन

ये लेख Google C ++ प्रोग्रामिंग मानकों जितना अच्छा है!

2
असल में ऐसा नहीं है। स्कॉटिश मेयर्स / हर्ब सुटर्स के न्यूनतम इंटरफ़ेस सिद्धांत के खिलाफ 'स्थिर तरीकों का उपयोग न करें' सलाह सीधे जाती है। उपयोगी सलाह हैं, लेकिन उनमें कई दिमागों के योगदान की कमी है।
मैथ्यू एम।

@FrankS आपने लिंक का क्रम क्यों बदल दिया? यह पहले अच्छे कालक्रम में था।
21

@ कवास वास्तव में कोई विचार नहीं था, जो चार साल से अधिक समय से था, इसलिए मुझे लगता है कि मेरे पास इसके कुछ कारण थे फिर :-)
फ्रैंक

15

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

आपकी सभी वस्तुओं में तब डेटा होगा, जो सिंगलटन में रहते थे। मुझे नहीं लगता कि कुल मिलाकर बहुत अंतर है, लेकिन यह आपके कोड को पढ़ना आसान बना सकता है।


1
मैं "सबसे अच्छा तरीका" कथन से सहमत नहीं हूं, लेकिन एक अच्छे विकल्प के लिए +1।
tylermac

इस दृष्टिकोण के साथ समस्या यह है कि हर नई वस्तु में (या संदर्भ) शामिल हैं जो संभावित रूप से डेटा का एक बड़ा हिस्सा हो सकता है। var_dump () उन gob युक्त ऑब्जेक्ट्स में से किसी पर भी बड़ी सूची में बहुत तेज़ी से पुनरावर्ती चेतावनियों के साथ स्वतंत्र रूप से शामिल होता है । यह बदसूरत है, यह बहुत कुशल नहीं हो सकता है, और चीजों को हियरवायर लगता है। हालाँकि, मैंने व्यक्तिगत रूप से एक बेहतर तरीका नहीं खोजा है। मैंने एक वैश्विक संदर्भ के लिए __construct () का उपयोग करके "फ़ैक्टरी" पद्धति को मोड़ दिया। ऐसा लगता है कि सब कुछ पीछे की ओर झुका हुआ है, हालांकि, खूंखार सिंगलटन से बचने के लिए ...
FYA

2
@EastGhostCom: हम सिंगलटन का उपयोग कर सकते हैं और चीजों को अपने लिए कठिन बनाने की कोशिश करना बंद कर सकते हैं :)
gbjbaanb

5

मैं यहाँ स्पष्ट कह सकता हूँ, लेकिन क्या कोई कारण है कि आप स्प्रिंग या गाइस जैसे डिपेंडेंसी-इंजेक्शन फ्रेमवर्क का उपयोग नहीं कर सकते हैं ? (मेरा मानना ​​है कि वसंत भी अब .NET के लिए भी उपलब्ध है)।

इस तरह, ढांचा विन्यास वस्तुओं की एक प्रति पकड़ सकता है, और आपकी सेम (सेवा, डीएओ, जो भी हो) को इसे देखने की चिंता करने की आवश्यकता नहीं है।

यह वह तरीका है जो मैं आमतौर पर लेता हूं!


4

यदि आप स्प्रिंग फ्रेमवर्क का उपयोग करते हैं , तो आप बस एक नियमित बीन बना सकते हैं। डिफ़ॉल्ट रूप से (या यदि आप स्पष्ट रूप से सेट होते हैं scope="singleton") केवल बीन का एक उदाहरण बनता है और हर बार बीन का उपयोग निर्भरता में किया जाता है या फिर से प्राप्त किया जाता है getBean()

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


3
ओह विडंबना - अपने सिंगलटन को बदलने के लिए (सिंगलटन) स्प्रिंग बीन्स का उपयोग करें ...
ज़ैक मैकोम्बर

4

विकल्प चीजों के लिए एक वस्तु पूछने के बजाय आपको जो चाहिए, उसमें पारित हो रहा है।


4

एक एकल कॉन्फ़िगरेशन ऑब्जेक्ट के लिए ज़िम्मेदारियों को जमा न करें क्योंकि यह एक बहुत बड़ी वस्तु में समाप्त हो जाएगा जो समझना और नाजुक दोनों मुश्किल है।

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

एक सामान्य, वैश्विक और बड़ी Configurationवस्तु से बचने के लिए अपने कोड को रीक्रिएट करने का प्रयास करें । ग्राहक वर्गों के लिए केवल आवश्यक पैरामीटर पास करें:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

इसके लिए refactored किया जाना चाहिए:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

एक निर्भरता इंजेक्शन फ्रेमवर्क यहाँ बहुत मदद करेगा, लेकिन इसकी सख्त आवश्यकता नहीं है।


हाँ यह वास्तव में अच्छी बात है। मैंने पहले भी ऐसा किया है। मेरे बड़े कॉन्फ़िगरेशन ऑब्जेक्ट MailServiceConf, ServerConf जैसे इंटरफेस को लागू कर रहे थे .. डिपेंडेंसी इंजेक्शन फ्रेमवर्क से कक्षाओं में कॉन्फ़िगरेशन पास करता है, इसलिए मेरी कक्षाएं बड़े कॉन्फ़िगरेशन ऑब्जेक्ट पर निर्भर नहीं थीं।
कैल्टंटास

1

आप स्थिर तरीकों का उपयोग करके सिंगलटन के समान व्यवहार को पूरा कर सकते हैं। स्टीव yegge इस पोस्ट में इसे बहुत अच्छी तरह से समझाते हैं ।


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

0

क्या एक ऐसा वर्ग जिसमें केवल स्थिर विधियाँ और क्षेत्र संभव हैं? मुझे यकीन नहीं है कि वास्तव में आपकी स्थिति क्या है, लेकिन यह देखने लायक हो सकता है।


1
यदि कक्षा स्टेटलेस है, तो उसे स्टेटिक क्लास होना चाहिए।
अल्बर्टोपीएल

1
यह C ++ में है - पैटर्न को मोनोस्टेट के रूप में जाना जाता है।

0

निर्भर करता है कि किस टूलिंग / फ्रेमवर्क आदि का उपयोग किया जा रहा है। निर्भरता इंजेक्शन / आईओसी उपकरण के साथ एक व्यक्ति को अक्सर अभी भी आवश्यक कक्षा के लिए di / ioc कंटेनर उपयोग सिंगलटन व्यवहार होने से एकल प्रदर्शन / अनुकूलन मिल सकता है - (जैसे कि एक IConfigSettings इंटरफ़ेस) केवल कक्षा का एक उदाहरण बनाकर। यह अभी भी परीक्षण के लिए प्रतिस्थापित किया जा सकता है

वैकल्पिक रूप से एक वर्ग बनाने के लिए एक कारखाने का उपयोग कर सकता है और आपके द्वारा अनुरोध किए जाने पर हर बार एक ही उदाहरण लौटाता है - लेकिन परीक्षण के लिए यह एक ठूंसा हुआ / नकली संस्करण लौटा सकता है।


0

कॉलबैक इंटरफ़ेस के रूप में कॉन्फ़िगरेशन करने की संभावना की समीक्षा करें। तो आपका कॉन्फ़िगरेशन संवेदनशील कोड दिखेगा:

MyReuseCode.Configure(IConfiguration)

सिस्टम-इनिट कोड दिखेगा:

Library.init(MyIConfigurationImpl)

0

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


0

शायद बहुत साफ भी नहीं है, लेकिन आप शायद उन सूचना बिट्स को पास कर सकते हैं जिन्हें आप उस विधि में बदलना चाहते हैं जो सिंगलटन बनाता है - बजाय उपयोग करने के

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

आप createSingleton(Information info)सीधे एप्लिकेशन स्टार्टअप पर कॉल कर सकते हैं (और यूनिट परीक्षणों के सेटअप-मेथड्स में)।


-1

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

वसंत, आदि का उपयोग करते हुए DI एक बहुत अच्छा विकल्प है, लेकिन एकमात्र विकल्प नहीं है।

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