C# 单身替代方案——是否等效?

C# 单身替代方案——是否等效?,c#,performance,c#-4.0,singleton,C#,Performance,C# 4.0,Singleton,快速提问- 我知道标准的单例模式如下: 起初的 但这段代码似乎没有必要。对我来说,您可以使用以下任何一种简单的设计模式来完成相同的任务: 版本2 版本3 在我看来,版本2似乎是实现这一点的最佳方法,因为它允许您传入参数(或不传入),但仍然有有限数量的实例。我的应用程序对延迟/性能相当敏感-这些模式中有没有任何一种可以提高性能 虽然第一次访问每个对象的时间似乎更长,但因为对象正在创建。而且,看起来原始字段的速度稍微慢了一点,因为每次有其他对象访问它时,它都必须检查其支持字段是否为null 提前感谢

快速提问-

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

起初的 但这段代码似乎没有必要。对我来说,您可以使用以下任何一种简单的设计模式来完成相同的任务:

版本2 版本3 在我看来,版本2似乎是实现这一点的最佳方法,因为它允许您传入参数(或不传入),但仍然有有限数量的实例。我的应用程序对延迟/性能相当敏感-这些模式中有没有任何一种可以提高性能

虽然第一次访问每个对象的时间似乎更长,但因为对象正在创建。而且,看起来原始字段的速度稍微慢了一点,因为每次有其他对象访问它时,它都必须检查其支持字段是否为null


提前感谢

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

请参见此场景:

public void BusinessLogicMethod()
{
    var initialValue = MySingleton.Instance.GetInitialValue();
    var processedValue = initialValue + specialSomething + businessLogic;
    MySingleton.Instance.SaveProcessedValue(processedValue);
}
现在,假设我想为这个方法编写一个单元测试。理想情况下,我希望编写一个指定输入和输出的测试,并且只测试业务逻辑。但是对于静态单例,方法的实现与单例的实现相关联。我可以在测试开始时轻松设置初始值,还是取决于其他因素/DB访问/其他因素

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

public void BusinessLogicMethod()
{
    var singleton = ServiceLocator.Resolve<MySingleton>();
    var processedValue = singleton.InitialValue + specialSomething + businessLogic;
    singleton.SaveProcessedValue(processedValue);
}
public void BusinessLogicMethod()
{
var singleton=ServiceLocator.Resolve();
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);
} 
public void TestBusinessLogic()
{
MySingleton fakeSingleton=new Mock();
Setup(s=>s.InitialValue).Returns(5);
//在ServiceLocator中注册假代码
ServiceLocator.Register(fakeSingleton.Object);
//跑
MyBusinessMethod();
//断言
fakeSingleton.Verify(s=>s.SaveProcessedValue()).Called(恰好.Once);
} 
不用担心真正的单例实现。

公共密封类单例
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()
    {
    }
}
{ private static readonly Lazy Lazy=new Lazy(()=>new Singleton()); 公共静态单例实例{get{return lazy.Value;}} 私人单身人士() { } }

快速、干净、线程安全。

我最喜欢的单例实现是:

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


(我需要仔细看看Peter Kiss的一个,它看起来也不错)

Singleton2与Singleton1不同,因为
实例的计算结果不是“懒惰的”。在Singleton1中,只有在访问实例时才创建实例,并且从那时起使用相同的实例。在SingleTon2中,实例在实际访问之前用类初始化。

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

查看本文
public void BusinessLogicMethod()
{
    var singleton = ServiceLocator.Resolve<MySingleton>();
    var processedValue = singleton.InitialValue + specialSomething + businessLogic;
    singleton.SaveProcessedValue(processedValue);
}
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);
} 
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()
    {
    }
}