2009-02-25 28 views
6

मैं सिंगलटन पैटर्न को लागू करने के लिए सबक्लास को मजबूर करना चाहता हूं।सबक्लास में फोर्स सिंगलटन पैटर्न

मूल रूप से मैंने मूल वर्ग में एक अमूर्त स्थैतिक संपत्ति होने का विचार किया, लेकिन इसके करीब, यह समझ में नहीं आया (सार आवश्यक और उदाहरण)।

अगला, मैंने एक स्थिर संपत्ति के साथ एक इंटरफ़ेस रखने का विचार किया, लेकिन यह भी समझ में नहीं आता है (इंटरफेस को भी एक उदाहरण की आवश्यकता होती है)।

क्या यह कुछ संभव है, या क्या मुझे इस विचार को छोड़कर एक अमूर्त कारखाना लागू करना चाहिए?

+0

मैं कुछ समय के लिए सिंगलेट के संबंध में बाड़ पर रहा हूं। लेकिन यह धागा उनको उपयोग न करने के लिए कुछ अच्छे अंक बनाता है: http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – JMD

+0

सैकड़ों धागे, ब्लॉग पोस्ट और कारणों से भरे लेख हैं सिंगलेट का उपयोग करने के लिए। यह बेहद दुर्लभ है कि वे वास्तव में आपके कोड में सुधार करते हैं। कृपया इसे पुनर्विचार करें। आप, और उस कोड के साथ काम कर रहे हर दूसरे डेवलपर, हर जगह plastering सिंगलेट्स पछतावा करने जा रहा है। – jalf

उत्तर

6

कृपया पुनर्विचार करें। आप यहां सिंगलेट का उपयोग नहीं करना चाहते हैं। आप अपनी कक्षा से प्राप्त उपयोगकर्ताओं के लिए कुछ कार्यक्षमता उपलब्ध करा रहे हैं। कोई बात नहीं। लेकिन आप एक विशिष्ट तरीके को भी निर्देशित कर रहे हैं जिसमें इसे हमेशा इस्तेमाल किया जाना चाहिए, और बिल्कुल कोई कारण नहीं है। वह ठीक नहीं है।

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

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

या आप किसी बिंदु पर अपने गेम में एकाधिक समान/समान स्तर रखने का निर्णय ले सकते हैं, जिसका अर्थ है कई उदाहरण बनाना।

एक सिंगलटन आपको दो बातें देता है:

  • एक गारंटी नहीं है कि वस्तु का कोई एक से अधिक उदाहरण कभी instantiated किया जाएगा, और कि उदाहरण

यदि आप के लिए

  • वैश्विक पहुँच इन दोनों चीजों की आवश्यकता नहीं है, बेहतर विकल्प हैं। आपको निश्चित रूप से वैश्विक पहुंच की आवश्यकता नहीं है। (ग्लोबल्स खराब हैं, और आमतौर पर खराब डिज़ाइन का एक लक्षण, विशेष रूप से आपके गेम स्टेटस जैसे म्यूटेबल डेटा में)

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

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

  • 4

    आईओसी कंटेनर का उपयोग करने का प्रयास करें। सबसे अच्छे आईओसी कंटेनर इसे स्वयं लागू करने के बिना सिंगलटन पैटर्न के उपयोग को सक्षम करते हैं (यानी: वसंत ढांचे) - मुझे यह स्थिर गेटिस्टेंस() विधि को मजबूर करने से बेहतर लगता है।

    इसके अलावा, यह जावा में वास्तव में संभव नहीं है, हालांकि यह टेम्पलेट्स के साथ सी ++ में काम करेगा।

    +0

    जो खुद को समग्र डिजाइन के लिए बहुत अच्छी तरह से उधार देगा। इसके अलावा, यह जावा के लिए नहीं है लेकिन सी # के लिए है। –

    +0

    वसंत में एक .NET आईओसी कंटेनर है। –

    +0

    यदि आप जटिल कुछ भी नहीं चाहते हैं तो आप अपना खुद का आईओसी कंटेनर रोल करने का भी प्रयास कर सकते हैं। यहां एक निर्माण करने के तरीके पर एक अच्छा डीएनआरटीवी पॉडकास्ट है: http://www.dnrtv.com/default.aspx?showNum=126 – Joseph

    0

    मैं एक सील वर्ग कि निर्माता को पारित कर दिया प्रतिनिधियों से अपनी कार्यक्षमता हो जाता है, कुछ इस तरह परिभाषित करेंगे:

    public sealed class Shape { 
        private readonly Func<int> areaFunction; 
    
        public Shape(Func<int> areaFunction) { this.areaFunction = areaFunction; } 
    
        public int Area { get { return areaFunction(); } } 
    } 
    

    यह उदाहरण भावना का एक बहुत नहीं है, यह सिर्फ दिखाता है एक पैटर्न। इस तरह के एक पैटर्न हर जगह इस्तेमाल नहीं किया जा सकता है, लेकिन कभी-कभी यह मदद करता है।

    public sealed class Shape { 
        private readonly Func<int> areaFunction; 
    
        private Shape(Func<int> areaFunction) { this.areaFunction = areaFunction; } 
    
        public int Area { get { return areaFunction(); } } 
    
        public static readonly Shape Rectangle = new Shape(() => 2 * 3); 
        public static readonly Shape Circle = new Shape(() => Math.Pi * 3 * 3); 
    } 
    
    +0

    आवृत्ति वापस करने के लिए स्थैतिक कॉल रखने का पूरा बिंदु यह है कि निर्माता अनुपलब्ध और बना रहे हैं कक्षा के बाहर के उदाहरण असंभव है। आप समाधान एकल सिंगल पैटर्न लागू नहीं करता है। –

    +0

    एक स्थैतिक वर्ग हमेशा एक सिंगलटन होता है (कुछ परिदृश्य होते हैं, जहां सिंगलटन के रूप में स्थैतिक वर्ग का उपयोग नहीं किया जा सकता है)। इस समाधान में स्थिर क्षेत्र/गुण जो समान परिणाम उत्पन्न करते हैं। –

    1

    क्यों:

    इसके अतिरिक्त, यह स्थिर क्षेत्रों की एक सीमित संख्या को बेनकाब करने के लिए बढ़ाया जा सकता है? अगर कोई आपकी कक्षा के उप-वर्ग के कई उदाहरणों का उपयोग करना चाहता है तो उनके पास एक पूरी तरह से वैध कारण हो सकता है।

    यदि आप ऐसा कुछ करना चाहते हैं जो प्रत्येक वर्ग के लिए केवल एक बार किया जाना चाहिए जो आपकी कक्षा को उपclass (क्यों, मुझे कोई जानकारी नहीं है, लेकिन आपके पास कोई कारण हो), बेस क्लास में एक शब्दकोश का उपयोग करें।

    +0

    प्रश्न में कक्षाएं काफी बड़ी वस्तुएं हैं जो 2 डी गेम में एक दृश्य का प्रतिनिधित्व करती हैं।मैं इन दृश्यों को फिर से बनाना नहीं चाहता हूं अगर उन्हें पहले बनाया गया है और मैं प्रत्येक दृश्य की राज्य जानकारी को उपयोग में नहीं रहना चाहता हूं। –

    +0

    आपको अपना प्रश्न संपादित करना चाहिए और इसे टेक्स्ट में जोड़ना चाहिए। मुझे लगता है कि यह लोगों द्वारा दिए गए उत्तरों को प्रभावित करेगा। –

    +0

    उस स्थिति में, आप कक्षा को सीलबंद और सिंगलटन दोनों चाहते हैं। आप दृश्य को एक अलग वर्ग में भी रखने पर विचार कर सकते हैं, जो सिंगलटन और मुहरबंद है, और उसके बाद मूल वर्ग पर सिंगलटन आवश्यकता को छोड़ दें। – erikkallen

    0

    मुझे लगता है कि आप यहां ईमानदार होने के लिए कारखाने के पैटर्न से बेहतर होंगे। या ब्रायन Dilley की तरह एक आईओसी उपकरण का उपयोग करें। सी # दुनिया में भार हैं, यहां सबसे लोकप्रिय हैं: कैसल/विंडसर, स्ट्रक्चर मैप, यूनिटी, निनजेक्ट।

    उस तरफ, मैंने सोचा कि वास्तव में आपकी समस्या को हल करने में मजा आएगा! इस पर एक नज़र डालें:

    //abstract, no one can create me 
    public abstract class Room 
    { 
        protected static List<Room> createdRooms = new List<Room>(); 
        private static List<Type> createdTypes = new List<Type>(); 
    
        //bass class ctor will throw an exception if the type is already created 
        protected Room(Type RoomCreated) 
        { 
         //confirm this type has not been created already 
         if (createdTypes.Exists(x => x == RoomCreated)) 
          throw new Exception("Can't create another type of " + RoomCreated.Name); 
         createdTypes.Add(RoomCreated); 
        } 
    
        //returns a room if a room of its type is already created 
        protected static T GetAlreadyCreatedRoom<T>() where T : Room 
        { 
         return createdRooms.Find(x => x.GetType() == typeof (T)) as T; 
        } 
    } 
    
    public class WickedRoom : Room 
    { 
        //private ctor, no-one can create me, but me! 
        private WickedRoom() 
         : base(typeof(WickedRoom)) //forced to call down to the abstract ctor 
        { 
    
        } 
    
        public static WickedRoom GetWickedRoom() 
        { 
         WickedRoom result = GetAlreadyCreatedRoom<WickedRoom>(); 
    
         if (result == null) 
         { 
          //create a room, and store 
          result = new WickedRoom(); 
          createdRooms.Add(result); 
         } 
    
         return result; 
        } 
    } 
    
    public class NaughtyRoom :Room 
    { 
        //allows direct creation but forced to call down anyway 
        public NaughtyRoom() : base(typeof(NaughtyRoom)) 
        { 
    
        } 
    } 
    
    internal class Program 
    { 
        private static void Main(string[] args) 
        { 
         //Can't do this as wont compile 
         //WickedRoom room = new WickedRoom(); 
    
         //have to use the factory method: 
         WickedRoom room1 = WickedRoom.GetWickedRoom(); 
         WickedRoom room2 = WickedRoom.GetWickedRoom(); 
    
         //actually the same room 
         Debug.Assert(room1 == room2); 
    
         NaughtyRoom room3 = new NaughtyRoom(); //Allowed, just this once! 
         NaughtyRoom room4 = new NaughtyRoom(); //exception, can't create another 
        } 
    } 
    

    विकेट्रूम एक ऐसी कक्षा है जो सिस्टम को सही ढंग से लागू करती है। किसी भी क्लाइंट कोड को सिंगलटन विकेट्रूम क्लास की पकड़ मिल जाएगी। NaughtyRoom सिस्टम को ठीक से लागू नहीं करता है, लेकिन यहां तक ​​कि इस वर्ग को दो बार तत्काल नहीं किया जा सकता है। एक अपवाद में एक दूसरा तत्काल परिणाम।

    +0

    यह मेरे वर्तमान कार्यान्वयन के समान है। मेरी समस्या यह है कि कुछ भी नहीं हो रहा है NaughtyRoom या WickedRoom अपने Get विधियों को लागू नहीं करने से। मैं सबक्लास को उन तरीकों को लागू करने के लिए मजबूर करना चाहता हूं। –

    0

    हालांकि यह उपयोगकर्ता को सिंगलटन उप-वर्ग रखने के लिए लागू नहीं करेगा, आप उपयोगकर्ता को कक्षा (या इसके उप-वर्ग) के केवल एक उदाहरण को नीचे के रूप में लागू करने के लिए लागू कर सकते हैं। यदि किसी उप-वर्ग का दूसरा उदाहरण बनाया गया है तो यह त्रुटि फेंक देगा।

    public abstract class SuperClass { 
    private static SuperClass superClassInst = null; 
    
    public SuperClass() { 
        if(superClassInst == null) { 
         superClassInst = this; 
        } 
        else { 
         throw new Error("You can only create one instance of this SuperClass or its sub-classes"); 
        } 
    } 
    
    public final static SuperClass getInstance() { 
        return superClassInst; 
    } 
    
    public abstract int Method1(); 
    public abstract void Method2(); 
    } 
    
    संबंधित मुद्दे