001-单例模式
在项目开发中,经常有这样的需求:某些特殊的类在系统中只存在一个实例,才能确保逻辑正确,效率良好.
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
——《设计模式》GoF
那么就有接下来的一些问题?
1:如何绕过普通的构造函数,提供一种机制来保证一个类只有一个实例
public sealed class Singleton
{
static Singleton instance=null;
private Singleton(){}
public static Singleton Instance
{
get
{
if(instance==null)
instance=new Singleton();
return instance;
}
}
}
以上对于线程来说不安全,单线程中已满足要求。
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
}
以上版本:
同一个时刻加了锁的那部分程序只有一个线程可以进入
对象实例由最先进入的那个线程创建
后来的线程在进入时(instence == null)为假,不会再去创建对象实例
增加了额外的开销,损失了性能
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
多线程安全
线程不是每次都加锁
允许实例化延迟到第一次访问对象时发生
public sealed class Singleton
{
private static readonly Singleton instance =null;
static Singleton()
{
instance = new Singleton();
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
依赖公共语言运行库负责处理变量初始化
公共静态属性为访问实例提供了一个全局访问点
对实例化机制的控制权较少(.NET代为实现)
静态初始化是在 .NET 中实现 Singleton 的首选方法
public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
private class Nested
{
static Nested()
{
instance= new Singleton();
}
internal static readonly Singleton instance=null;
}
}
初始化工作由Nested类的一个静态成员来完成,这样就实现了延迟初始化
Singleton模式中的实例构造器可以设置为protected以允许子类派生。
Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
Singleton模式是限制而不是改进类的创建。
理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。