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