Singleton Alternative - 它是等同的吗?

时间:2012-02-26 08:37:28

标签: c# performance c#-4.0 singleton

快速提问 -

我知道标准单例模式如下:

原始

public class Singleton1
{

    public static Singleton1 _Instance;
    public static Singleton1 Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = new Singleton1();
            }
            return _Instance;
        }
    }

    private Singleton1()
    {

    }
}

但似乎这段代码是不必要的。对我来说,你可以用以下任何一种简单的设计模式来完成同样的事情:

第2版

public class Singleton2
{
    public static readonly Singleton2 Instance = new Singleton2();

    private Singleton2()
    {
    }
}

第3版

public class Singleton3
{
    static Singleton3()
    {
    }
}

对我而言,似乎版本2是执行此操作的优越方法,因为它允许您传入参数(或不传递)但仍具有有限数量的实例。我的应用程序具有相当的延迟/性能敏感性 - 这些模式中的任何一种都有性能提升吗?

似乎虽然第一次访问每个人会更长,因为正在创建对象。此外,看起来原始的那个稍微慢一点,因为它必须检查每当其他东西访问它时它的支持字段是否为空。

先谢谢!

5 个答案:

答案 0 :(得分:7)

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}

快速,干净,线程安全。

答案 1 :(得分:3)

作为静态实例实现的单例的一个问题是它们使测试和模拟更加困难。

请参阅此方案:

public void BusinessLogicMethod()
{
    var initialValue = MySingleton.Instance.GetInitialValue();
    var processedValue = initialValue + specialSomething + businessLogic;
    MySingleton.Instance.SaveProcessedValue(processedValue);
}

现在,假设我想为此方法编写单元测试。理想情况下,我想编写一个指定输入和输出的测试,并仅测试业务逻辑。但是对于静态单例,该方法的实现与单例的实现相关联。我可以在测试开始时轻松设置InitialValue,还是依赖于其他因素/ DB访问/什么?

但是,如果我使用非静态单例,加上一些依赖注入或服务定位器模式,我可以构建我的函数:

public void BusinessLogicMethod()
{
    var singleton = ServiceLocator.Resolve<MySingleton>();
    var processedValue = singleton.InitialValue + specialSomething + businessLogic;
    singleton.SaveProcessedValue(processedValue);
}

我的测试可以像这样,使用模糊的Moq式模拟语法:

public void TestBusinessLogic()    
{
    MySingleton fakeSingleton = new Mock<MySingleton>();
    fakeSingleton.Setup(s => s.InitialValue).Returns(5);

    // Register the fake in the ServiceLocator
    ServiceLocator.Register<MySingleton>(fakeSingleton.Object);

    // Run
    MyBusinessMethod();

    // Assert        
    fakeSingleton.Verify (s => s.SaveProcessedValue()).Called(Exactly.Once);
} 

不用担心REAL单例实现。

答案 2 :(得分:1)

Singleton2与Singleton1不同,因为Instance未评估“懒惰”。在Singleton1中,仅在访问实例时创建实例,然后在使用相同实例时创建实例。在SingleTon2中,Instance使用类进行初始化,然后才能实际访问。

答案 3 :(得分:0)

我最喜欢的单身实现是这样的: http://www.codeproject.com/Articles/14026/Generic-Singleton-Pattern-using-Reflection-in-C

确保您的.ctor不公开,这是最常见的错误,然后,它是安全/完全可重用的。

(我需要仔细看看Peter Kiss'看起来不错的那个)

答案 4 :(得分:0)

要回答您的性能问题,检查私有字段是否为空所花费的时间可以忽略不计。因此,我不会担心它在性能方面如何实施。