单例模式有以下特点:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
一个典型的单例类的实现如下所示:其中构造子私有表示子类不能被继承。
public class Singleton
{
private static Singleton m_instance = null;
private Singleton()
{
}
public static Singleton getInstance()
{
if(m_instance==null)
{
m_instance=new Singleton();
}
return m_instance;
}
}
单线程的Singleton模式
public class Singleton
{
private static Singleton instance;
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
}
多线程的Singleton模式
public class Singleton
{
private static volatile Singleton instance = null;
private static object lockHelper = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
使用.net特有的支持多线程的单件模式代码
public sealed class Singleton
{
public static readonly Singleton Instance = new Singleton();
private Singleton() { }
}
代码说明:
- sealed 修饰符表示该类是密封类,不能被继承。你可以按需修改。
- 这里readonly关键字只是不希望客户程序将Instance字段设置为null等不合理的值。
- *** static *** = new Singleton(); 是使用了内联初始化技术,这部分初始化其实是在static Singleton()中执行的。即上面的代码相当于:
public sealed class Singleton
{
public static readonly Singleton Instance;
static Singleton()
{
Instance = new Singleton();
}
private Singleton() { }
}
- 上述代码在编译时,会使用一个名为beforefieldinit元数据标志。此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法在第一次访问该类型的静态字段之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有 beforefieldinit,运行库就必须在某个精确时间运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。
- 静态构造器自身就可以保证,多线程情况下,系统就可以保证只有一个执行。
缺点:
不支持参数化单件构造器。即静态构造器不支持参数,就导致我们无法利用静态构造器实现传参数的单件。