सिंगलटन / ग्लोबल्स के विकल्प


16

मैंने सिंगलटन / ग्लोबल्स के नुकसान के बारे में अनगिनत बार सुना है, और मुझे समझ में आता है कि वे इतने बार क्यों डूब जाते हैं।

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

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

बस ऐसा लगता है कि मैं cluttered निर्भरता इंजेक्शन के लिए वैश्विक राज्य डेटा का व्यापार कर रहा हूं, उन वस्तुओं को डेटा पास कर रहा है जो डेटा के बारे में परवाह नहीं करते हैं, केवल बाल वस्तुओं पर इसे पारित करने के उद्देश्य के अलावा।

क्या यह एक ऐसा मामला है जहां एक सिंगलटन एक अच्छी बात होगी, या क्या कोई सुरुचिपूर्ण समाधान है जो मुझे याद आ रहा है?

जवाबों:


16

एकल और ग्लोबल्स को भ्रमित न करें। जबकि कुछ प्रकार के वैश्विक चर आमतौर पर आवश्यक होते हैं, सिंगलटन केवल एक वैश्विक चर के लिए प्रतिस्थापन नहीं है , बल्कि मुख्य रूप से C ++ ( और FQA ) में स्थैतिक आरंभीकरण क्रम की समस्याओं के आसपास काम करने का एक तरीका है । (अन्य भाषाओं में, यह विभिन्न भाषाओं की कमियों के आसपास काम करने का एक तरीका है, जैसे वैश्विक चर और नंगे कार्यों की कमी।)

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

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


+1। सेवा लोकेटर पैटर्न लिंक के लिए अच्छा जवाब और धन्यवाद। यह एक बहुत ही दिलचस्प पढ़ा है।
बंमज़ैक

1

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

आपके उदाहरण के मामले में, क्या आपके पास "AssetManager" का कोई प्रकार नहीं हो सकता है जो परिसंपत्तियों को लोड और संग्रहीत करेगा, और फिर ScreenManager को केवल उस (शायद निर्माण पर) एक संदर्भ देने की आवश्यकता होगी? इस अर्थ में, आप किसी अन्य ऑब्जेक्ट में लिपटे हुए संपत्तियों के संदर्भों को पास कर रहे हैं, और जब आवश्यक हो, तो आप इसे पत्ती फ़ंक्शन को पास करने के बजाय एक बार, प्रारंभिककरण पर, पास कर सकते हैं।

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


1

मुझे लगता है कि जेसन डी बिल्कुल सही है - यह है कि मैं इसे कैसे संभालूंगा:

गेम में एसेटमैनगर का एक उदाहरण है, एक ऐसी वस्तु जिससे आप नाम से कोई भी संपत्ति प्राप्त कर सकते हैं।

खेल में:

assetManager = new AssetManager();
screenManager = new ScreenManager();
screenManager.assetManager = assetManager;

स्क्रीन मैनजर में:

screen = new Screen();
screen.assetManager = assetManager;

स्क्रीन में:

myAsset = assetManager.getBitmp("lava.png");

अब सभी स्क्रीनों के पास किसी भी संपत्ति की जरूरत है। यह ग्लोबल्स या सिंग्लेटन्स का उपयोग करने की तुलना में कोई अधिक जटिल या पागल नहीं है, और आपके पास गेम के 2 उदाहरण हैं जो बिना किसी संघर्ष के एक ही एप्लिकेशन में चल रहे हैं। मुझे एक बार एक खेल बनाना था जो 8 मिनी-गेम से बना था, सभी एक ही बेस क्लास / फ्रेमवर्क साझा कर रहे थे। मुझे इस संदर्भ पासिंग स्टाइल का उपयोग करने के लिए अपने सभी ग्लोबल्स / सिंगलेट्स को रिफ्लेक्टर करना पड़ा, और मैंने कभी पीछे मुड़कर नहीं देखा। ग्लोबल्स वाली एकमात्र चीजें ऐसी चीजें हैं जो केवल एक बार शारीरिक रूप से मौजूद हो सकती हैं, जैसे कि ऑडियो, नेटवर्किंग, आई / ओ आदि।


0

आप सिंगलटन को बदलने के लिए फ़ैक्टरी पैटर्न का उपयोग कर सकते हैं । तब फैक्ट्री क्लास का नियंत्रण होता है कि आप कितने उदाहरण बना सकते हैं, जिन्हें आप बाद में आसानी से बदल सकते हैं जब आपको लगता है कि आपको एक से अधिक की आवश्यकता है AssetManagerजैसा कि इस लेख में कहा गया है :

यह आपको सिंग्लटन के सभी लचीलेपन के साथ देता है, और कई समस्याओं के समीप है।


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

स्थैतिक तरीके ग्रेनाइट की तरह लचीले होते हैं। हर बार जब आप एक का उपयोग करते हैं, तो आप अपने कार्यक्रम का हिस्सा कंक्रीट में डाल रहे हैं। बस यह सुनिश्चित करें कि आप अपने पैर वहाँ नहीं है क्योंकि आप इसे कठोर देख रहे हैं। किसी दिन आप आश्चर्यचकित होंगे कि, गोश द्वारा, आपको वास्तव में उस खतरे के एक और कार्यान्वयन की आवश्यकता है PrintSpooler वर्ग, और यह एक इंटरफ़ेस, एक कारखाना और कार्यान्वयन कक्षाओं का एक सेट होना चाहिए था। डी 'ओह!

यह स्थैतिक विधियों के बारे में है, लेकिन इसे स्थैतिक कक्षाओं में भी लागू किया जा सकता है।


"कक्षा को स्थिर बनाने" से आपका क्या तात्पर्य है? C ++ में स्थिर कक्षाएं नहीं हैं। क्या आपका मतलब केवल स्थैतिक तरीके हैं? एक नाम स्थान के बजाय एक वर्ग होने पर परेशान क्यों?

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