C# 单例设计模式总结,附源码

单例设计模式:保证一个类永远只实例化一次。
而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
code: https://github.com/net-web/C-demo.git


1、多线程不安全的实现

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

namespace ConsoleApplication1
{
    public sealed class SingleInstance
    {
        private static SingleInstance instance;
        private SingleInstance() { }
        public static SingleInstance Instance
        {
            get{
                if (null == instance)
                {
                    instance = new SingleInstance();
                }
                return instance;
            }
        }
    }
}

sealed 表示SingleInstance不能被继承。其实private 构造函数,就限制了这个类不能被继承了。加一个sealed只是为了可读性。

2、安全的单例模式

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

namespace ConsoleApplication1
{
    public class SafeSingleInstance
    {
        private static volatile SafeSingleInstance instance;
        private static readonly object obj = new object();
        private SafeSingleInstance() { }
        public static SafeSingleInstance Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (obj)//锁
                    {
                        if (instance == null)
                        {
                            instance = new SafeSingleInstance();
                        }
                    }
                }
                return instance;
            }
        }
    }
}

这种方式,加锁保护,保证实例只被创建一次。但是涉及到锁和解锁,比较消耗资源。


3、只读属性的单例模式

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

namespace ConsoleApplication1
{
    public class SingleInstanceReadonly
    {
        private static readonly SingleInstanceReadonly instance = new SingleInstanceReadonly();
        private SingleInstanceReadonly() { }
       public static SingleInstanceReadonly Instance
       {
           get
           {
               return instance;
           }
       }
    }
}

这种方式...... 我比较喜欢,简单...嘿嘿嘿,但是这种方式,在Main函数执行第一句话之前,instance其实已经被赋值了,并不是预期的 只有到访问Instance变量时才创建对象。
需要修改一下,将构造函数改为静态。


4、使用Lazy,线程安全

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

namespace ConsoleApplication1
{
    class SingleInstanceLazy
    {
        private static readonly Lazy<SingleInstanceLazy> instance = new Lazy<SingleInstanceLazy>(() => new SingleInstanceLazy());
        private SingleInstanceLazy() { }
        public static SingleInstanceLazy Instance
       {
           get
           {
               return instance.Value;
           }
       }
    }
}

5、泛型单例

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Begin");
            mySingle.Instance.age = 500;
            Console.WriteLine(mySingle.Instance.age);
        }
    }

    public abstract class SingleInstance<T>
    {
        private static readonly Lazy<T> _instance = new Lazy<T>(() =>
        {
            var ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            if (ctors.Count() != 1)
                throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.", typeof(T)));
            var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate);
            if (ctor == null)
                throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.", typeof(T)));
            return (T)ctor.Invoke(null);
        });
        public static T Instance
        {
            get { return _instance.Value; }
        }
    }

    public class mySingle : SingleInstance<mySingle>
    {
        private mySingle() { }
        public int age;
    }
}

标签: 单例设计模式, 饿汉模式, c#单例设计模式

添加新评论