2010-05-18 11 views
8

होने के लिए सार बेस क्लास को एक सारणी वर्ग कैसे बना सकता है जो प्रत्येक व्युत्पन्न कक्षाओं को सिंगलटन के लिए मजबूर करेगा? मैं सी # का उपयोग करता हूँ।प्रत्येक व्युत्पन्न कक्षाओं को सिंगलटन

+0

क्या आपको इसे अमूर्त होने की आवश्यकता है? आप एक सामान्य सिंगलटन कक्षा बना सकते हैं। हालांकि यह अभी भी प्रकार की वस्तुओं को पुन: स्थापित करना संभव होगा T. –

+0

हां। सार आधार को उप-वर्गों को सिंगलटन होना चाहिए। –

उत्तर

2

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

public abstract class Singleton 
{ 
    private static readonly object locker = new object(); 
    private static HashSet<object> registeredTypes = new HashSet<object>(); 

    protected Singleton() 
    { 
     lock (locker) 
     { 
      if (registeredTypes.Contains(this.GetType())) 
      { 
       throw new InvalidOperationException(
        "Only one instance can ever be registered."); 
      } 
      registeredTypes.Add(this.GetType()); 
     } 
    } 
} 

public class Repository : Singleton 
{ 
    public static readonly Repository Instance = new Repository(); 

    private Repository() 
    { 
    } 
} 
+1

यह सिंगलटन नहीं है। सिंगलटन पैटर्न के साथ 'getInstance' पर आपका कॉल हमेशा सफल रहेगा। आपका प्रस्ताव वास्तव में केवल एक रन-टाइम चेक है जो सिंगलटन पैटर्न का कोई लाभ प्रदान नहीं करता है। – ewernli

5

जो काम नहीं करेगा क्योंकि सिंगलटन को कहीं भी स्थिर पहुंच की आवश्यकता है और इसे मजबूर नहीं किया जा सकता है।

singletonimplemention + उदाहरण के लिए

देखें: Implementing the Singleton Pattern in C#

+0

लेख वास्तव में शानदार है। मैं एक निष्कर्ष तक पहुंच रहा था कि यह संभव नहीं होगा लेकिन मैं अभी भी विचारों की तलाश में हूं। –

+1

संदर्भ के लिए अद्यतन लिंक है: http://csharpindepth.com/Articles/General/Singleton.aspx – Seph

2

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

1

जावा या सी # में कक्षाएं "प्रथम श्रेणी" नहीं हैं। कक्षा के स्थैतिक भाग को उत्तराधिकारी द्वारा वंचित या ओवरराइड नहीं किया जा सकता है। अधिक जानकारी के लिए this answer देखें। इसके अलावा, आपके पास मेटा-क्लास की अवधारणा नहीं है।

स्मॉलटॉक या रूबी जैसी भाषाओं में, आप एक नया मेटाक्लास Singleton परिभाषित कर सकते हैं जो getInstance विधि को परिभाषित करता है। फिर आप ClassA और ClassB को परिभाषित कर सकते हैं Singleton मेटाक्लास के उदाहरण हो सकते हैं। फिर दोनों वर्ग स्वचालित रूप से एक विधि getInstance का पर्दाफाश करते हैं जिसका उपयोग objectA या objectB उदाहरण बनाने के लिए किया जा सकता है। क्या वह अच्छा नहीं है? खैर, व्यावहारिक रूप से आप अक्सर मेटाक्लास का उपयोग नहीं करते हैं, और सिंगलटन वास्तव में उनका एकमात्र उपयोग है जो समझ में आता है और मुझे पता है।

1

यह करने के लिए यहां एक (बदसूरत) तरीका है। यह शायद सरलीकृत और सुधार किया जा सकता है, लेकिन यह मेरा पहला कदम है।

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

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

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

public abstract class Singleton<T> where T : Singleton<T> 
{ 
    protected Singleton(SingletonKey key) { } 
    private static SingletonKey _key; 
    private static SingletonKey Key 
    { 
     get 
     { 
      if (_key == null) SingletonKey.Initialize(); 
      return _key; 
     } 
    } 
    protected class SingletonKey 
    { 
     private SingletonKey() 
     { 
     } 
     public static void Initialize() 
     { 
      if (_key == null) 
      { 
       _key = new SingletonKey(); 
      } 
     } 
    } 

    protected static Func<SingletonKey, T> Creator; 
    private static T instance; 
    public static T Instance 
    { 
     get 
     { 
      if (instance == null) instance = Creator(Key); 
      return instance; 
     } 
    } 
} 

public class MySingleton : Singleton<MySingleton> 
{ 
    public string Name { get; set; } 
    public static void Initialize() 
    { 
     Creator = (key) => new MySingleton(key); 
    } 
    protected MySingleton(SingletonKey key) : base(key) 
    { 
    } 
} 
0

मुझे विश्वास है कि मैंने कुछ समान हासिल करने की कोशिश की है यानी एक सामान्य इंटरफेस और कक्षाओं के समूह पर सिंगलटन पैटर्न को लागू करने की कोशिश की।

// Common interface of my singleton classes 
public interface IMySingletonClass 
{ 
    string ValueGetter(); 

    void ValueSetter(string value); 
} 

// Generic abstract base class 
public abstract class Singleton<T>: IMySingletonClass 
{ 
    private static readonly object instanceLock = new object(); 
    private static T instance; // Derived class instance 

    // Protected constructor accessible from derived class 
    protected Singleton() 
    { 
    } 

    // Returns the singleton instance of the derived class 
    public static T GetInstance() 
    { 
     lock (instanceLock) 
     { 
      if (instance == null) 
      { 
       instance = (T)Activator.CreateInstance(typeof(T), true); 
      } 
      return instance; 
     } 
    } 

    // IMySingletonClass interface methods 
    public abstract string ValueGetter(); 

    public abstract void ValueSetter(string value); 
} 

// Actual singleton class 
public class MySingletonClass : Singleton<MySingletonClass> 
{ 
    private string myString; 

    private MySingletonClass() 
    { 
     myString = "Initial"; 
    } 

    public override string ValueGetter() 
    { 
     return myString; 
    } 

    public override void ValueSetter(string value) 
    { 
     myString = value; 
    } 
} 

यहाँ एक साधारण परीक्षण है: यह मेरा समाधान था

class Program 
{ 
    static void Main(string[] args) 
    { 
     MySingletonClass r1 = MySingletonClass.GetInstance(); 
     Console.WriteLine("R1 value = {0}", r1.ValueGetter()); 
     r1.ValueSetter("Changed through R1"); 
     MySingletonClass r2 = MySingletonClass.GetInstance(); 
     Console.WriteLine("R2 value = {0}", r2.ValueGetter()); 

     Console.ReadKey(); 
    } 
} 

कृपया ध्यान दें आप आसानी से सामान्य सार सिंगलटन वर्ग से आम इंटरफेस निकाल सकते हैं कि अगर आप सिर्फ बुनियादी "टेम्पलेट" की जरूरत है ।

संबंधित मुद्दे