我正在学习如何实现一些基本的设计模式。在学习Singleton模式的同时,我注意到网络上有两种常见的实现方式:
// Possibly from: http://www.yoda.arachsys.com/csharp/singleton.html
// I cannot remember exact source, sorry :(
public sealed class Singleton
{
// Static members are 'eagerly initialized', that is,
// immediately when class is loaded for the first time.
// .NET guarantees thread safety for static initialization
private static readonly Singleton instance = new Singleton();
// Private constructor prevents instantiation from other classes
private Singleton() { }
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
public static Singleton() { }
// Get the instance of the singleton
public static Singleton getInstance()
{
return instance;
}
}
和:
public class Singleton
{
// Static, VOLATILE variable to store single instance
private static volatile Singleton m_instance;
// Static synchronization root object, for locking
private static object m_syncRoot = new object();
// Property to retrieve the only instance of the Singleton
public static Singleton Instance
{
get
{
// Check that the instance is null
if (m_instance == null)
{
// Lock the object
lock (m_syncRoot)
{
// Check to make sure its null
if (m_instance == null)
{
m_instance = new Singleton();
}
}
}
// Return the non-null instance of Singleton
return m_instance;
}
}
}
答案 0 :(得分:3)
我绝对会考虑你的第一次实施......
第二个似乎对我有疑问......如果你需要/想要一个懒惰的实现,你可以使用Lazy<T>
- 因为它是框架的一部分,感觉更舒服..
BTW:还有更多方法可以实现Singleton模式...... here is an excellent article。
答案 1 :(得分:2)
我不确定,但看起来你从这里得到了这些例子:http://www.yoda.arachsys.com/csharp/singleton.html
如果没有,请仔细阅读。关于这两个版本有几点想法。 如果您个人问我:如果我需要知道单身是否已经初始化,我会选择第二个解决方案。
如果您不必处理多线程,我会使用更简单的方法(参见参考链接中的“错误代码”示例)。
答案 2 :(得分:2)
第一个是安全和懒惰的。
static constructor
保证只在第一次访问Instrance
之前执行一次。如果存在静态构造函数(即使为空),则保证静态字段初始化直接在静态构造函数之前执行。如果没有静态构造函数,则可以更早地进行字段初始化。
第二个是懒惰的,但我不确定双锁模式是否有效。我怀疑它已经坏了,至少在ECMA内存模型中是这样。
在大多数情况下,我个人都会避免任何Class.Instance
单例模式支持IoC单例。
答案 3 :(得分:1)
1)这完全是一种设计选择。在需要时预先启动或初始化。
2)是的,它是线程安全的,因为CLR保证单线程对象初始化。 (静态和实例)
修改
就个人而言,在第一个例子中,我将Instance字段公之于众,并免除了getter。有兴趣知道这是不是一个坏主意?
答案 4 :(得分:1)
这是一个单身人士所以我会选择选项1,除非它是一个并不总是需要的大型物体。但我可能不会为那些通常根本没用过的东西做单身。
答案 5 :(得分:0)
两种实现方式都很好,因此取决于您的需求。
如果性能不是问题,请使用第一个的热切创建的实例。否则,使用第二个,其中仅同步第一个访问。