快速提问 -
我知道标准单例模式如下:
public class Singleton1
{
public static Singleton1 _Instance;
public static Singleton1 Instance
{
get
{
if (_Instance == null)
{
_Instance = new Singleton1();
}
return _Instance;
}
}
private Singleton1()
{
}
}
但似乎这段代码是不必要的。对我来说,你可以用以下任何一种简单的设计模式来完成同样的事情:
public class Singleton2
{
public static readonly Singleton2 Instance = new Singleton2();
private Singleton2()
{
}
}
public class Singleton3
{
static Singleton3()
{
}
}
对我而言,似乎版本2是执行此操作的优越方法,因为它允许您传入参数(或不传递)但仍具有有限数量的实例。我的应用程序具有相当的延迟/性能敏感性 - 这些模式中的任何一种都有性能提升吗?
似乎虽然第一次访问每个人会更长,因为正在创建对象。此外,看起来原始的那个稍微慢一点,因为它必须检查每当其他东西访问它时它的支持字段是否为空。
先谢谢!
答案 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)
要回答您的性能问题,检查私有字段是否为空所花费的时间可以忽略不计。因此,我不会担心它在性能方面如何实施。