6. 单例模式(Singleton Pattern)

 

一、介绍
用途:在某些情况下,某些对象在整个程序运行的过程中只需要一个就可以了,或者不需要。举例:一台电脑可以连接多台打印机,但是当程序运行起来开始打印时,只允许一台打印机输出所打印的内容。
简单的来说,单例模式(单件模式)的作用是在保证在整个应用程序的生命周期中,任何时刻,单例类的实例只能存在一个(或者一个都不存在)。
作用:全局访问,实例化控制
 
设计模式结构图:
            
二、代码实现
C# 代码实现:
 
创建:
    /// <summary>
    /// 懒汉式单例模式
    /// </summary>
    public class SingletonV0
    {
        // 声明一个静态类的变量
        private static  SingletonV0 _singleton = null;
        //构造方法私有,防止外界用new()访问
        private SingletonV0(){}
        //通过此方法获取实例
        public static SingletonV0 GetInstance()
        {
            return _singleton ?? (_singleton = new SingletonV0());
        }

    }

 

使用:
 class Program
    {
        static void Main(string[] args)
        {
            Singleton singletonOne = Singleton. GetInstance();
            Singleton singletonTwo = Singleton. GetInstance();
            if (singletonOne.Equals(singletonTwo))
            {
                Console.WriteLine("singletonOne 与 singletonTwo 代表同一个实例!");
            }
            else
            {
                Console.WriteLine("singletonOne 与 singletonTwo 代表不同的实例!");
            }
        }
    }  

 

输出结果:
三、总结
单例模式的特点:
1. 单例模式在程序的任何时刻都只有一个实例
2. 单例的构造函数是私有的,外部程序想要访问这个单例的话,只能通过GetInstance()来请求
3. 在GetInstance()内部实现 单例的不存在则创建,存在则返回
四、拓展
多线程情况下的单例模式:
 
以上代码看上去很简单,单例模式的代码量不会超过10行,但是在多线程情况下就蛋疼了,当第一个线程进来,判断singleton为null,正准备要创建,第二个线程也进来了,这时候if判断singleton为null,这就会创建两个singleton的实例。
 
解决方法:
既然是多线程进来的,那我们就可以考虑线程锁;让一个线程先进if语句块,然后在外面将if语句块加锁,当第二个线程再进来时,就会阻塞处于阻塞状态,直到第一个线程弯沉if判断并且创建了singleton实例,再判断singleton的存在与否,执行接下来的代码,这样就完美解决。
 
lock 是确保当一个线程位于代码的临界时,另一个线程不进入临界区,如果其他线程试图进入锁定代码时,则它将一直等待(直到该对象被释放)
 
代码修改如下:
 
 public static Singleton GetInstance() 
        {
            //下面使用了双重检查锁定
            //第一重判断
            if (singleton == null)
            {
                lock(syncObject)
                {
                    //第二重判断
                    //在这里可以保证只实例化一次,即使再次调用也不会创建新的实例
                    if (singleton == null)
                    {
                        singleton = new Singleton();
                    }
                }
            }
            
            return singleton;
        }  

 

 
懒汉式饿汉式单例类:
上述单例类为懒汉式单例类,因为只有调用GetInstance()才会创建singleton的实例,而下代码为饿汉式单例类
namespace Singleton
{
    public sealed class Singleton 
    { 
        private static readonly Singleton singleton = new Singleton();

        private Singleton() 
        {
        }
        public static Singleton GetInstance() 
        {
            return singleton;
        }
    }
}

 

在整个类被加载时,就会创建实例,而非调用GetInstance()再创建,故这是一种饿汉单例
 
 
 
 
posted @ 2019-05-01 07:59  NCat  阅读(135)  评论(0)    收藏  举报