Singleton模式主要作用是保证在应用程序中,一个类只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。另外方面,Singleton也能够被无状态化。提供工具性质的功能,
1、模式分类
从目的来看主要有:
(1)创建型(Creational)模式:负责对象创建
(2)结构型(Structural)模式:处理类与对象间的组合
(3)行为型(Behavioral)模式:类与对象交互中的职责分配
从范围来看:
(1)类模式处理类与子类的静态关系
(2)对象模式处理对象间的动态关系
2、动机(Motivation)
在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
这应该是类设计者的责任,而不是使用者的责任
3、意图(Intent)
保证一个类仅有一个实例,并提供一个该实例的全局访问点 ——《设计模式GoF》
4、结构(Structure)

5、单线程Singleton模式实现
public class Singleton
{
    private static Singleton instance;
    private Singleton(){}
    public static Singleton Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}
私有的实例构造器是为了屏蔽默认产生的构造器,让类的使用者无法调用构造器。
单线程Singleton模式的几个要点
(1)Singleton模式中的实例构造器可以设置为protected以允许子类派生。
(2)Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
(3)Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
(4)Singleton模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。
多线程Singleton模式实现
class Singleton
{
    private static volatile singleton instance = null;
    private static object lockHelper = new object();
    private Singleton() {}
    public static Singleton Instance()
    {
        if (instance == null)
        {
            lock (lockHelper)
            {
                if(instance == null)
                {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
关于volatile修饰:编译器在编译代码的时候会对代码的顺序进行微调,用volatile修饰保证了严格意义的顺序。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
使用.NET类型初始化机制实现多线程Singleton模式
class Sigleton
{
    public static readonly Singleton Instance = new Singleton();
    private Singleton() { }
}
以上是内联初始化(生成的同时进行初始化)的单例模式,它等同于:
class Singleton
{
    public static readonly Singleton Instance;
    static Singleton()
    {
        Instance = new Singleton();
    }
    private Singleton() {  }
}
内联初始化其实是把静态的字段放到静态构造器去初始化。反编译出内联初始化的代码可以看出以上结论,反编译出的内联初始化代码如下:
.nethod private hidebysig specialnane rtspecialnane static
           void  .cctor() cil nanaged
{
    //Code size                           11(0xb)
    .naxstack        8
    IL_0000:  newobj    instance void Singleton::.ctor()
    IL_0005:  stfld          class Singleton Singleton::Instance
    IL_000a:  ret 
}  //end of method Singleton :: .cctor
只要想访问静态字段,必定已经在之前执行了静态构造器。这样也能够精确地保证使用的时候一定能拿到实例,如果不使用也不会实例化对象,也就是延时加载的功能。他同样能够支持多线程环境,因为只可能有一个线程执行静态构造器,不可能有多个线程去执行静态构造器,感觉就是程序已经自动为我们加锁了。
它的一点弊端就是它不支持参数化的实例化方法。在.NET里静态构造器只能声明一个,而且必须是无参数的,私有的。因此这种方式只适用于无参数的构造器。
Singleton模式扩展
将一个实例扩展到n个实例,例如对象池的实现。(n不是指无限个实例,而是固定的某个数)
将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。
.NET框架中的Singleton应用
MyClass c1 = new MyClass();
MyClass c2 = new MyClass();
Type t1 = c1.GetType();
Type t2 = c2.GetType();
t1==t2 这说明,GetType方法获得的Type实例都是单例。
HttpContext.Current也是如此,他们是通过Singleton的扩展方式实现的,他们的单例也并不是覆盖所有领域,只是针对某些局部领域中,是单例的,不同的领域中还是会有不同的实例。
新闻热点
疑难解答