C#设计模式:单例模式(Singleton)

一,单例模式:它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量-唯一一个,就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。

1,静态方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SingletonPattern
{
    public class Singleton
    {
        private Singleton()
        {
            Console.WriteLine("{0}被创建了,线程ID{1}!", this.GetType().Name, Thread.CurrentThread.ManagedThreadId);
        }

        public static Singleton _singleton = null;
        public static object lockObject = new object();
        /// <summary>
        ///创建实例
        /// </summary>
        /// <returns></returns>
        public static Singleton CreateIntance()
        {
            if (_singleton == null)   //保证对象初始化之后的所有线程,不需要等待锁
            {
                Console.WriteLine("准备进入Lock");
                lock (lockObject)  //保证只有一个进程去判断
                {
                    if (_singleton == null) //保证为空才正的创建
                    {
                        _singleton = new Singleton();
                    }
                }
            }
            return _singleton;
        }

        public void Show()
        {
            Console.WriteLine("显示!!!");
        }
    }
}

2,静态构造单例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SingletonPattern
{
    public class SingletonSecond
    {
        public static SingletonSecond _singleton = null;
        private SingletonSecond()
        {
            Console.WriteLine("{0}被创建了,线程ID{1}!", this.GetType().Name,Thread.CurrentThread.ManagedThreadId);
        }
        /// <summary>
        ///1,静态构造函数:由CLR保证,再第一次使用这个类型之前,调用而且之调用一次
        /// </summary>
        /// <returns></returns>
        static SingletonSecond()
        {
            _singleton = new SingletonSecond();
        }
        public static SingletonSecond CreateIntance()
        {
            return _singleton;
        }

        public void Show()
        {
            Console.WriteLine("显示!!!");
        }
    }
}

3,静态变量单例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SingletonPattern
{
    public class SingletonThird
    {
    
        private SingletonThird()
        {
            Console.WriteLine("{0}被创建了,线程ID{1}!", this.GetType().Name,Thread.CurrentThread.ManagedThreadId);
        }
        /// <summary>
        /// 静态变量:会在类型第一次使用的时候初始化,而且只初始化一次
        /// </summary>
        private static SingletonThird _singleton = new SingletonThird();
        public static SingletonThird CreateIntance()
        {
            return _singleton;
        }

        public void Show()
        {
            Console.WriteLine("显示!!!");
        }
    }
}

4,输出结果

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 单例模式
    /// 保证整个进程中该对象只被实例化一次,常驻内存,根据这个特点:单例模式有三种写法:Singleton,SingletonSecond,SingletonThird,
    /// 普通的类型是需要的时候初始化,使用完被GC回收,跟静态不一样
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //Singleton singleton = Singleton.CreateIntance();
            //for (int i = 0; i < 10; i++)
            //{
            //    Singleton singleton = Singleton.CreateIntance();
            //    singleton.Show();
            //}
            Console.WriteLine("---------------------------------------");
            //多线程测试调用,结果也是公用一个对象,之调用一次构造函数
            List<IAsyncResult> asyncResults = new List<IAsyncResult>();
            for (int i = 0; i < 5; i++)
            {
                asyncResults.Add(new Action(() =>
                {
                    Singleton singleton = Singleton.CreateIntance();
                    singleton.Show();
                }).BeginInvoke(null,null));  //会启动一个异步多线程的调用
            }

            ////判断多线程是否执行完了
            while (asyncResults.Count(r => !r.IsCompleted) > 0)
            {
                Thread.Sleep(10);
            }

            Console.WriteLine("---------------------------------------");
            //多线程测试调用,结果也是公用一个对象,之调用一次构造函数
            List<IAsyncResult> asyncResults2 = new List<IAsyncResult>();
            for (int i = 0; i < 5; i++)
            {
                asyncResults2.Add(new Action(() =>
                {
                    SingletonSecond singleton = SingletonSecond.CreateIntance();
                    singleton.Show();
                }).BeginInvoke(null, null));  //会启动一个异步多线程的调用
            }

            ////判断多线程是否执行完了
            while (asyncResults2.Count(r => !r.IsCompleted) > 0)
            {
                Thread.Sleep(10);
            }

            Console.WriteLine("---------------------------------------");
            List<IAsyncResult> asyncResults3 = new List<IAsyncResult>();
            for (int i = 0; i < 5; i++)
            {
                asyncResults3.Add(new Action(() =>
                {
                    SingletonThird singleton = SingletonThird.CreateIntance();
                    singleton.Show();
                }).BeginInvoke(null, null));  //会启动一个异步多线程的调用
            }
            Console.ReadKey();
        }
    }
}

得到的结果都是一样的,共有对象,都是被构造一次

二,单例模式的扩展

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _1_2单例模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Demo.Instance.Say();
        }
    }

    public class SingleTon<T> where T : new()
    {
        private static T _instance;
        public static T Instance
        {
            get { return _instance = new T(); }
        }
    }

    public class Demo : SingleTon<Demo>
    {
        public void Say()
        {
            Console.WriteLine("单例模式");
        }
    }
}

三:单例模式(Singleton)的特点

1,私有构造函数,原因使用者不可以实例,则单例模式全局只有一个实例

2,静态实例,因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以定义一个私有的静态全局变量instance来保存该类的唯一实例;

3,单例模式避免多线程并发造成实例并不唯一,则需要用到锁。锁的解析如以上代码。

原文地址:https://www.cnblogs.com/May-day/p/5681884.html