1、设计一个类,我们只能生成该类的一个实例。
解法一:由于只能生成一个实例,因此必须把构造函数设为私有函数以禁止他人创建实例。我们可以定义一个静态的实例,在需要的时候创建该实例。
public sealed class Singleton1
{
private Singleton1()
{
}
private static Singleton1 instance = null;
public static Singleton1 Instance
{
get
{
if(instance == null)
instance = new Singleton1();
return instance;
}
}
}
上述代码在Singleton1的静态属性Instance中,只有在instance为null的时候才创建一个实例以避免重复创建。同时我们把构造函数定义为私有函数,这样能确保只创建一个实例。
但如果有两个线程同时运行到判断instance是否为null的if语句,并且instance的确没有创建时,那么两个线程都会创建一个实例,此时类型Singleton1就不再满足单例模式的要求了。
解法二:加一个同步锁。假设有两个线程同时想创建一个实例,由于在一个时刻只有一个线程能得到同步锁,另一个只能等待。但锁是很耗时的操作。
public sealed class Singleton2
{
private Singleton2()
{
}
private static readonly object syncObj = new object();
private static Singleton2 instance = null;
public static Singleton2 Instance
{
get
{
lock(syncObj)
{
if(instance == null)
instance = new Singleton2();
}
return instance;
}
}
}
解法三:加同步锁前后两次判断实例是否已存在。
public sealed class Singleton3
{
private Singleton3()
{
}
private static object syncObj = new object();
private static Singleton3 instance = null;
public static Singleton3 Instance
{
get
{
if(instance == null)
{
lock(syncObj)
{
if(instance == null)
instance = new Singleton3();
}
}
return instance;
}
}
}
Singleton3中只有当instance为null即没有创建时,需要加锁操作。当instance已经创建出来之后,则无须加锁。因为只在第一次的时候instance为null,因此只在第一次试图创建实例的时候需要加锁。
推荐解法一:利用静态构造函数
C#的静态构造函数能确保只调用一次,在此时初始化静态变量。
public sealed class Sinleton4
{
private Singleton4()
{
}
private static Singleton4 instance = new Singleton4();
public static Singleton4 Instance
{
get
{
return instance;
}
}
}
在Singleton4中,实例instance并不是第一次调用属性Sinleton4.Instance的时候创建,而是在第一次用到Singleton4的时候就会被创建。
推荐解法二:实现按需创建实例
public sealed class Sinleton5
{
Singleton5()
{
}
public static Singleton5 Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton5 instance = new Singleton5();
}
}
当我们第一次试图通过属性Singleton5.Instance得到Singleton5的实例时,会自动调用Nested的静态构造函数创建实例instance。如果我们不调用属性Singleton5.Instance,那么就不会触发.NET运行时调用Nested,也不会创建实例,真正做到了按需创建。