设计模式—单例模式

单例模式

Singleton单例:一个类在有且只有一个实例,并提供一个全局的访问点,私有化构造函数,提供一种机制来保证一个类只有一个实例。

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

四种实现方式:

  • 简单模式
namespace 大话设计模式
{
    /// <summary>
    /// 简单实现单例
    /// </summary>
    public sealed class SimpleSingleton
    {
        SimpleSingleton()
        {
        }

        public string Name { get; set; }

        private static SimpleSingleton singleton;

        public static SimpleSingleton Instance
        {
            get
            {
                if(singleton==null)
                {
                    singleton=new SimpleSingleton();
                }
                return singleton;
            }
        }

        public  void  GetStr()
        {
            Console.WriteLine(Name);
        }
    }
}

      优点:通过私有化构造函数,私有静态变量存储实例,通过静态属性访问实例,只有私有实例变量不为空时,才初始化对象。
      缺点:无法保证线程安全。 

  • 安全线程

线程安全是在访问唯一实例时,将通过padlock来锁住唯一实例对象,这样就防止在多线程的情况下,创造出多个对象。

namespace 大话设计模式
{
    public sealed class ThreadSafeSingleton
    {
        private static readonly object padLock = new object();

        private static ThreadSafeSingleton threadSafeSingleton;

        public string Name { get; set; }

        public int Index = 0;

        private ThreadSafeSingleton()
        {
            Name =Guid.NewGuid().ToString();
            Thread.Sleep(2000);
        }

        public void Introduce()
        {
            Index++;
            Console.WriteLine(Thread.CurrentThread.Name+"——》key:"+Name);
            Console.ReadLine();
        }

        public static ThreadSafeSingleton Instance()
        {
          
                if (threadSafeSingleton == null)
                {
                    lock (padLock)
                    {
                        if (threadSafeSingleton == null)
                        {
                            threadSafeSingleton = new ThreadSafeSingleton();
                        }
                    }
                }
                return threadSafeSingleton;
            
        }


    }
}

线程安全分为两种:单锁和双重锁定,因为单例的特殊性,我们只需要保证是程序域中只有唯一的实例,因此我们只需要在实例为null的时候进行锁定,可以大大节省系统开销

我们通过多线程调用

  • namespace 大话设计模式
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 10; i++)
                {
                    Thread thread = new Thread(DoSomThing);
                    thread.Name = "线程:" + i;
                    thread.Start();
                }
                Console.ReadLine();
            }
    
            public  static  void DoSomThing()
            {
               var sigleton= ThreadSafeSingleton.Instance();
                sigleton.Introduce();
            }
        }
    }

     有锁结果如图:

所有线程都是调用同一个对象

我们将锁注释掉以后调用结果如下

每个线程调用的对象不是同一个,因此违反了单例原则。

  • 静态初始化

首先我们需要知道静态类的初始化顺序:静态字段,静态构造函数,静态方法的调用先后顺序

namespace 大话设计模式
{
    public  static class SingletonStaic
    {
        private static string filedStatic = ExportStr("我是字段");

        public static string ExportStr(string str)
        {
            Console.WriteLine(str);
            return str;
        }

        static SingletonStaic()
        {
            Console.WriteLine("我是构造函数");
        }

        public static void MethodStaic1()
        {
            Console.WriteLine("我是方法一");
        }

        public static void MethodStaic2()
        {
            Console.WriteLine("我是方法二");
        }
    }
}

调用

namespace 大话设计模式
{
    class Program
    {
        static void Main(string[] args)
        {
             SingletonStaic.MethodStaic1();
             SingletonStaic.MethodStaic2();
            Console.ReadLine();
        }
    }
}

因此调用先后顺序(静态字段——》静态构造函数——》静态方法)且静态字段和静态构造函数只调用一次

  • 延迟加载

 就是利用以上特性,利用内部类实现

原文地址:https://www.cnblogs.com/cainiaoguoshi/p/3428238.html