Singleton Factory生成多个单例实例

时间:2017-09-10 23:36:33

标签: c# singleton

我的项目中有两个单例类。

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;
        }
    }
}

我的同事建议创建一个单例类(something like a singleton factory),它接受一个通用接口并生成这两个singleton objects

如何做到这一点。

2 个答案:

答案 0 :(得分:2)

首先,你的类根本没有实现单例。看看这个:

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

_vsManager将始终为null,因此每次访问实例时都会创建多个实例。它应该是:

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

这就是确保只创建一个实例的方式。

另外,我会使用属性而不是函数,它更清楚:

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;
            }
        }
    }
}

然后您可以使用每个示例VStateManager.Instance.XXX

其次,为什么你需要第三堂课来创造这些单身人士?当你需要使用它们来访问GetXXXX时会创建所需的实例,有没有理由在你需要之前创建这些实例?

如果您真的需要在需要之前初始化这些实例,那么您可以做一些非常简单的事情:

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

然后初始化只需致电Initializer.Init()。无任何理由过度复杂代码是编程中所有邪恶的根源,不要试图解决不存在的问题,因为该解决方案可能会产生实际问题。

答案 1 :(得分:1)

您正在寻找的单件工厂可以使用泛型创建。您需要传递您需要创建单例实例的类型,并且工厂将返回该类型的实例,并确保只创建该类型的一个实例。

这种单件工厂的基本实现如下:

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;
    }
}

以下是您如何使用此工厂。

class Program
{

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

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

        Console.ReadKey();
    }
}

SingletonFactory的实现是一个非常基本的版本。并且它具有限制,它只能用于具有默认构造函数的类型。

但是可以进一步扩展到使用DI模块初始化实例而不必担心它们的构造函数。此外,它还可以扩展为将实例存储在其他地方,然后是字典,如缓存,内存缓存或数据库。

我希望这可以帮助你得到你想要的任何东西。