c#.net单例模式的学习记录!

 

一、 单例(Singleton)模式

 

单例模式的特点:

 

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其它对象提供这一实例。

 

单例模式应用:

 

  • 每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。
  • 一个具有自动编号主键的表可以有多个用户同时使用,但数据库中只能有一个地方分配下一个主键编号。否则会出现主键重复。

 

单例模式三种写法:

第一种最简单,但没有考虑线程安全,在多线程时可能会出问题。

public class Singleton
{
    private static Singleton instance = null;//定义一个实例对象
    private Singleton(){}//构造函数
    public static Singleton CreateInstance()//获得实例的方法
    {
        if(instance == null)//当前单例模式对象为空则创建

        {
            instance = new Singleton();
        }
        return instance;
    }
}

第二种考虑了线程安全,经典写法

public class Singleton
{
    private volatile static Singleton instance = null;//关于volatile: volatile多用于多线程的环境,当一个变量定义为volatile时,读取这个变量的值时候每次都是从内存里面读取而不是从缓存cache读。这样做是为了保证读取该变量的信息都是最新的,而无论其他线程如何更新这个变量。参考资料:官方文档
    private static readonly object lockObj = new object();
    private Singleton(){}
    public static Singleton CreateInstance()
    {
        if(instance == null)
        {
            lock(lockObj )
            {
                if(instance == null)
                     instance = new Singleton();
            }
        }
        return _instance;
    }
}

第三种.NET Framework平台优势实现Singleton模式的代码

public class Singleton
{

    private Singleton(){}
    public static readonly Singleton instance = new Singleton();
}  

 

非常吃惊是不是,不仅代码减少了许多,同时也解决了线程问题带来的性能上损失。有避免了编译器优化的问题。上述的代码真的能正常工作吗?如果能,那么它又是怎样工作的呢?

 

    注意到,Singleton类被声明为sealed,以此保证它自己不会被继承,其次没有了Instance的方法,将原来instance成员变量变成public readonly,并在声明时被初始化。通过这些改变,我们确实得到了Singleton的模式,原因是在JIT的处理过程中,如果类中的static属性被任何方法使用时,.NET Framework将对这个属性进行初始化,于是在初始化Instance属性的同时Singleton类实例得以创建和装载。而私有的构造函数和readonly(只读)保证了Singleton不会被再次实例化,这正是Singleton设计模式的意图。

 

在什么情形下使用单例模式:

使用Singleton模式有一个必要条件:在一个系统要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就不要使用单例模式。

注意:不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放,带来问题。

posted @ 2016-12-20 10:18  拾诚  阅读(270)  评论(0编辑  收藏  举报