2017-09-10 4 views
-2

Ich habe zwei Singleton-Klassen in meinem Projekt.Singleton Factory produziert mehrere Singleton-Instanzen

public class VStateManager : IVState 
{ 
    private static readonly object _createLock = new object(); 
    private static VStateManager _vsManager = null; 
    public static VStateManager GetVStateManager() 
    { 
     lock (_createLock) 
     { 
      if (_vsManager == null) 
      { 
       return new VStateManager(); 
      } 
      return _vsManager; 
     } 
    } 
} 

public class VTRFactory : IVTR 
{ 
    private static VehicleFactory _VTRFactory =null; 
    private static readonly object _createLock = new object(); 

    public static VehicleFactory GetVTRFactory() 
    { 
     lock(_createLock) 
     { 
      if(_VTRFactory == null) 
      { 
       return new VTRFactory(); 
      } 
      return _VTRFactory; 
     } 
    } 
} 

Mein Kollege schlug eine Singleton-Klasse (something like a singleton factory) zu erstellen, die eine generische Schnittstelle akzeptiert und produziert sowohl diese singleton objects

Wie dies geschehen kann.?

Antwort

2

Zunächst implementieren Ihre Klassen Singleton überhaupt nicht. Schauen Sie sich diese:

if (_vsManager == null) 
{ 
    return new VStateManager(); 
} 
return _vsManager; 

_vsManager wird immer null, so dass mehrere Instanzen wird jedes Mal, wenn Sie die Instanz zugreifen erstellt werden. Es sollte sein:

if (_vsManager == null) 
{ 
    _vsManager = new VStateManager(); 
} 
return _vsManager; 

So stellen Sie sicher, dass nur eine Instanz erstellt wird.

Außerdem würde ich eine Eigenschaft anstelle einer Funktion verwenden, ist es klar:

public class VStateManager : IVState 
{ 
    private static readonly object _createLock = new object(); 
    private static VStateManager _vsManager = null; 
    public static VStateManager Instance 
    { 
     get 
     { 
      lock (_createLock) 
      { 
       if (_vsManager == null) 
       { 
        _vsManager = new VStateManager(); 
       } 
       return _vsManager; 
      } 
     } 
    } 
} 

Dann können Sie pro Beispiel VStateManager.Instance.XXX verwenden.

Zweitens, warum brauchen Sie eine dritte Klasse, um diese Singletons zu erstellen? Wenn Sie sie verwenden müssen, indem Sie auf GetXXXX zugreifen, wird die erforderliche Instanz erstellt. Gibt es einen Grund, diese Instanzen zu erstellen, bevor Sie sie benötigen?

Wenn Sie wirklich diese Instanzen müssen initialisiert werden, bevor sie benötigt werden, dann können Sie etwas sehr einfach tun, wie folgt:

public static class Initializer() 
{ 
    public static void Init() 
    { 
     var a = VStateManager.GetVStateManager(); 
     var b = VehicleFactory.GetVTRFactory(); 
    } 
} 

Dann einfach Initializer.Init() rufen zu initialisieren. Den Code ohne Grund zu komplizieren, ist die Wurzel allen Übels in der Programmierung. Versuche nicht, ein Problem zu lösen, das nicht existiert, da diese Lösung echte Probleme verursachen kann.

1

Die Singleton-Fabrik, die Sie suchen, kann mit Generics erstellt werden. Sie müssen den Typ übergeben, für den Sie eine Singleton-Instanz erstellen müssen, und die Factory gibt eine Instanz dieses Typs zurück, wobei sichergestellt wird, dass nur eine Instanz dieses Typs erstellt wird.

Die grundlegende Implementierung einer solchen Singleton-Fabrik würde wie folgt aussehen.

public static class SingletonFactory 
{ 
    private static readonly object lockObject = new object(); 
    //Dictionary to store the singleton objects 
    private static readonly Dictionary<string, object> singletonObjects = new Dictionary<string, object>(); 

    // Method to retrieve singleton instance. 
    // Note the constraint "new()". This indicates that this method can be called for the types which has default constructor. 
    public static T GetSingletoneInstance<T>() where T:new() 
    { 
     var typeName = typeof(T).Name; 
     T instance; 

     lock (lockObject) 
     { 
      // Check in the dictionary if the instance already exist. 
      if (singletonObjects.ContainsKey(typeName)) 
      { 
       //Retrieve the instance from the dictionary. 
       instance = (T) singletonObjects[typeName]; 
      } 
      else 
      { 
       // If it does not exist in the dictionary, 
       // create a new instance 
       // and store it in the dictionary. 
       lock (lockObject) 
       { 
        instance = new T(); 

        singletonObjects.Add(typeName, instance); 
       } 
      } 
     } 

     // Return the instance of type "T" either retrieved from dictionary 
     // or the newly created one. 
     return instance; 
    } 
} 

Folgendes ist, wie Sie diese Fabrik verwenden.

class Program 
{ 

static void Main(string[] args) 
    { 
     var vstateManager = SingletonFactory.GetSingletoneInstance<VStateManager>(); 

     var vehicleFactory = SingletonFactory.GetSingletoneInstance<VehicleFactory>(); 

     Console.ReadKey(); 
    } 
} 

Die Implementierung von SingletonFactory ist eine sehr einfache Version. Und es hat eine Einschränkung, dass es nur für die Typen verwendet werden kann, die einen Standardkonstruktor haben.

Aber es kann weiter erweitert werden, um das DI-Modul zu verwenden, um die Instanzen zu initialisieren, ohne sich um ihre Konstruktoren kümmern zu müssen. Es kann auch erweitert werden, um die Instanzen an einem anderen Ort als einem Wörterbuch wie Cache, Memcaches oder Datenbank zu speichern.

Ich hoffe, dass dies Ihnen helfen würde, zu bekommen, was auch immer Sie suchen.

Verwandte Themen