Singleton几种单例模式

 

三板斧保证强制单例

 1.构造函数私有化,避免重复构造

 2.公开静态方法提供实例,这样外部才可以使用

 3.静态变量共享,保证全局对象唯一

三板斧下来,就可以保证多次使用该对象,也一直是同一个实例!

 public  class Singleton
    {
        private Singleton()//构造函数私有化
        {
            long iResult = 0;
            for (int i = 0; i < 100-000-000; i++)
            {
                iResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name} 完成构造...");
        }
        private static Singleton singleton = null;//静态变量
        public static Singleton CreateInstance()//公开的静态方法
        {
            if (singleton == null)
            {
                singleton = new Singleton();
            }
            return singleton;
        }
        public  void Show()
        {
            Console.WriteLine($"{this.GetType().Name}Show。。。。");
        }
}

看效果....

 

 当然,这种形式的单例,只适用于单线程。如果是多线程就不能保证是一个对象只实例化一次

 多线程?

 

 很多程序在单线程下跑的很好。却经不起多线程的考验,然而多线程是无法避免的,那我们继续改进一下代码

 接下来我们继续改造一下多线程的单例模式,使用的是lock锁,简单粗暴的就属它。

public  class Singleton
    {
        private Singleton()
        {
            long iResult = 0;
            for (int i = 0; i < 100-000-000; i++)
            {
                iResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name} 完成构造...");
        }
        private static Singleton singleton = null;
        private static readonly object singleton_Lock = new object();
        public static Singleton CreateInstance()
        {
            if (singleton == null)
            {
                lock (singleton_Lock)//保证方法块只有一个线程可以进入
                {
                    Console.WriteLine("进入lock排队....");
                    Thread.Sleep(1000);
                    if (singleton == null)
                    {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
        public  void Show()
        {
            Console.WriteLine($"{this.GetType().Name}Show。。。。");
        }
    }

调用看一下效果

 

 这就到达了我们想要的效果。

当然还有更简便的方法,前面的属于懒汉模式,下面这两种称之为饿汉模式,我们往下看代码.....

 public  class SingletonSecond
    {
        private SingletonSecond()
        {
            long iResult = 0;
            for (int i = 0; i < 100-000-000; i++)
            {
                iResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name} 完成构造...");
        }

        private static SingletonSecond Instance = null;
        /// <summary>
        /// 静态函数构造:由CRL调用,在类型第一次被调用前,且只调用一次
        /// </summary>
        static SingletonSecond()
        {
            Instance = new SingletonSecond();
        }
        public static SingletonSecond CreateInstance()
        {
            return Instance;
        }
        public  void Show()
        {
            Console.WriteLine($"{this.GetType().Name}Show。。。。");
        }
        public static void DoNothing()
        {
            Console.WriteLine("DoNothing");
        }
    }

还有一种静态字段的单例模式,实现方式如下:

 public  class SingletonThird
    {
        private SingletonThird()
        {
            long iResult = 0;
            for (int i = 0; i < 100-000-000; i++)
            {
                iResult += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"{this.GetType().Name} 完成构造...");
        }

        private static SingletonThird Instance = new SingletonThird ();
        /// <summary>
        /// 静态字段:由CRL调用,在类型第一次被使用前初始化,且只调用一次
        /// </summary>
     
        public static SingletonThird CreateInstance()
        {
            return Instance;
        }
        public  void Show()
        {
            Console.WriteLine($"{this.GetType().Name}Show。。。。");
        }
        public static void DoNothing()
        {
            Console.WriteLine("DoNothing");
        }
    }

 最后,对比一下单例模式和普通实例

 

   看起来单例模式好像还不如普通实例,但是为啥又有单例模式呢?到底什么时候使用?

   二者答案是一个,常规情况下,不推荐使用单例模式(项目使用IOC时,单例类都不需要自行实现了,直接可以用容器来完成单例)

   只有在场景要求必须是单例的时候,我们才会去使用单例,比如:数据库连接池、线程池、IOC容器实例等等。一个进程只需一个实例,多个实例反而容易出现问题!!

 

posted @ 2022-01-22 23:25  Valoris  阅读(38)  评论(0编辑  收藏  举报