2012-09-27 4 views
8

के लिए dispatch_once के साथ एक सिंगलटन क्लास बनाना मेरे पास 2 बाल वर्ग हैं जो 'MyClass' से प्राप्त होते हैं और प्रत्येक बाल वर्ग को सिंगलटन होना चाहिए।कक्षा hiearchy

मैं एक स्थिर उदाहरण प्राप्त करने के लिए इस पद्धति का उपयोग किया है मैं विरासत में किसी भी अन्य वर्गों की जरूरत नहीं है जब:

+ (MyClass *)getInstance 
{ 
    static dispatch_once_t once; 
    static MyClass *instance; 

    dispatch_once(&once, ^{ 
     instance = [[MyClass alloc] init]; 
    }); 

    return instance; 
} 

यह काम करता है सिर्फ महान। अब, यदि मैं दो नए बाल वर्ग, फर्स्ट क्लास और सेकेंड क्लास जोड़ता हूं, जिनमें से दोनों MyClass से प्राप्त होते हैं, तो मैं कैसे सुनिश्चित करूं कि मैं संबंधित बाल क्लास वापस प्राप्त करूं?

dispatch_once(&once, ^{ 
    // No longer referencing 'MyClass' and instead the correct instance type 
    instance = [[[self class] alloc] init]; 
}); 

FirstClass *firstClass = [FirstClass getInstance]; // should be of FirstClass type 
SecondClass *secondClass = [SecondClass getInstance]; // should be of SecondClass type 

ऊपर कर मतलब यह है कि मैं हमेशा वापस पाने के लिए जो भी वर्ग मैं अपने द्वितीय श्रेणी प्रकार के रूप में 1 instantiated:

first: <FirstClass: 0x884b720> 
second: <FirstClass: 0x884b720> 
// Note that the address and type as identical for both. 

को getInstance विधि जोड़ने के बिना संबंधित बच्चे वर्ग एकमात्र बनाने के लिए सबसे अच्छा तरीका क्या है प्रत्येक बच्चे वर्ग?

उत्तर

6

जब तक आपके पास कोई अच्छा कारण न हो, तो आपको आम तौर पर सिंगलटनिंग से बचने चाहिए। यह एक बहुत भ्रमित स्थिति बनाता है। यदि आप सिंगलटन MyClass बनाते हैं, तो क्या आप एक सिंगलटन FirstClass बना सकते हैं? चूंकि FirstClass हमेशा उपयोग योग्य होना चाहिए MyClass उपयोग योग्य (लिस्कोव द्वारा) है, अब तीन "सिंगलटन" MyClass ऑब्जेक्ट्स हैं। अब ओब्जेक सिंगलेट्स के साथ बहुत ढीला है, और यह एक अच्छी बात है, लेकिन यह अभी भी बहुत अजीब है।

ठीक है, उसने कहा, आपकी समस्या के बारे में क्या? पहला समाधान, फिर जवाब। समाधान यह है कि MyClass शायद ऊपर एक चर्चा के रूप में एक सिंगलटन नहीं होना चाहिए। सुपरक्लास में getInstance से छुटकारा पाएं और इसे सबक्लास में परिभाषित करें।

आपके dispatch_once में जो हो रहा है उसका उत्तर है। आप सभी मामलों में एक ही स्थिर once टोकन पास कर रहे हैं। dispatch_once किसी दिए गए टोकन के लिए कभी भी से अधिक नहीं चलाएगा। इसके आस-पास एकमात्र तरीका प्रत्येक वर्ग के लिए विभिन्न टोकन पास करना है, और मुझे प्रत्येक फ़ाइल में dispatch_once कोड को डुप्लिकेट किए बिना ऐसा करने का सुविधाजनक तरीका पता नहीं है। आप प्रत्येक सबक्लास के लिए अलग-अलग once टोकन बनाने का प्रयास कर सकते हैं, लेकिन sharedInstance विधि को डुप्लिकेट करने की तुलना में यह अधिक परेशानी और कोड होने की संभावना है।

बीटीडब्ल्यू, इसे getInstance पर कॉल न करें। ओबीजेसी में "मिल" का विशेष अर्थ है, और इसका मतलब यह नहीं है कि यहां, इसलिए यह भ्रमित है। इसे आमतौर पर sharedInstance कहा जाता है, या बेहतर sharedSomething जहां आपकी कक्षा "कुछ" है।यदि आप वास्तव में इसका मतलब है कि MyClass होना चाहिए और FirstClass होना चाहिए और SecondClass होना चाहिए, तो आप तीनों में sharedInstance लागू कर सकते हैं।

+0

मेरे पास इस पदानुक्रम का कारण यह है कि मेरे पास साझा साझा कोड और डेटा की संख्या है जो मेरे सभी बच्चों के वर्गों में (साझा किए गए 'के बाहर है। यही कारण है कि मैं विरासत बनाम प्रोटोकॉल का उपयोग कर रहा हूं। मैं भी चाहता था व्युत्पन्न कक्षाओं के सभी तीनों के लिए एक ही तत्काल कोड दोहराएं। –

+0

"प्राप्त करें" नामकरण के बारे में +1। –

1

आप जानते हैं कि सिंगलेट्स ग्रेनरी हैं, है ना? कई सिंगलेट्स एक बड़ी समस्या है। सावधानी का अंत


आप बेस सिंगलटन बनाने के लिए केवल dispatch_once का उपयोग कर सकते हैं। तो आपके आधार पर नक्शा प्राप्त हो सकता है (उदा। शब्दकोश {कुंजी: कक्षा नाम | मूल्य: इंस्टेंस}) इसके व्युत्पन्न प्रकारों के।

कि आप dispatch_once का उपयोग कर रहे हैं, यह सुझाव देता है कि इसका उपयोग बहु-संदर्भित संदर्भ में किया जाएगा। उस स्थिति में, आपको mutex का उपयोग करके शब्दकोश के साथ बातचीत की रक्षा करने की आवश्यकता होगी।

तो उप-वर्गों से आपके संदेश मैसेजिंग क्लास (self) के आधार पर निर्धारित करेंगे जो देखने के लिए कक्षा (उस उदाहरण को बनाते हुए, यदि आवश्यक हो)।

+1

लोग एकमात्र उपयोग करने के लिए और फिर उन्हें द्वारा खराब हो पता करने के लिए सीखने के लिए मिल गया है तुम क्यों मतलब वे कर रहे हैं से लगता है एक 'बड़ी समस्या'। – mskw

+0

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

0

उपयोग id में अपने Firstclass में myClass इस

+(instancetype)sharedInstance 
{ 
    static id sharedInstance; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     sharedInstance = [[[self class] alloc] init]; 
    }); 
    return sharedInstance; 
} 

की तरह मैं इस काम करता है चाहिए