欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单例模式的五种写法

程序员文章站 2022-07-13 23:37:46
...
  1. 常规写法(懒汉式),用在单线程,会有多线程问题
//常规写法
public sealed class Singleton1
{
    private Singleton1()
    {
        Debug.Log("执行了 Singleton1 构造函数");
    }

    private static Singleton1 m_Instance;
    public static Singleton1 Instance
    {
        get
        {
            if (m_Instance == null)
            {
                m_Instance = new Singleton1();
            }
            return m_Instance;
        }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singleton1");
    }
}

  1. 加同步锁法,考虑多线程安全问题,不过该写法每次都加锁是比较耗时的操作,所以有了第三种写法
//加同部锁
public sealed class Singleton2
{
    private Singleton2()
    {
        Debug.Log("执行了 Singleton2 构造函数");
    }

    private static Object SyncObj = new Object();

    private static Singleton2 m_Instance;
    public static Singleton2 Instance
    {
        get
        {
            lock (SyncObj)
            {
                if (m_Instance == null)
                {
                    m_Instance = new Singleton2();
                }
            }
            return m_Instance;
        }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singleton2");
    }
}

  1. 加同步锁+前后判断,在加锁之前之后都判断一次实例是否已创建,如果已创建则直接得到该实例,不去加锁,不过该写法写起来比较复杂
public sealed class Singleton3
{
    private Singleton3()
    {
        Debug.Log("执行了 Singleton3 构造函数");
    }

    private static Object SyncObj = new Object();

    private static Singleton3 m_Instance;
    public static Singleton3 Instance
    {
        get
        {
            if (m_Instance == null)
            {
                lock (SyncObj)
                {
                    if (m_Instance == null)
                    {
                        m_Instance = new Singleton3();
                    }
                }

            }
            return m_Instance;
        }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singlegon3");
    }
}

  1. 利用静态构造函数法(饿汉式),利用静态构造函数只会执行一次的特性。有两种写法,不过区别不大
//利用静态构造函数
//第一种(更简便点)
public sealed class Singleton4
{
    private Singleton4()
    {
        Debug.Log("执行了 Singleton4 构造函数");
    }
    private static Singleton4 m_Instance = new Singleton4();   
    public static Singleton4 Instance
    {
        get { return m_Instance; }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singleton4");
    }
}

//第二种
public sealed class Singleton4
{
    private Singleton4()
    {       
    }
    private static Singleton4 m_Instance = null;
    //静态构造函数
    static Singleton4()
    {
	    m_Instance = new Singleton4();
        Debug.Log("执行了 Singleton4 静态构造函数");
    }

    public static Singleton4 Instance
    {
        get { return m_Instance; }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singleton4");
    }
}

  1. 利用嵌套内部类,初始化工作由内部类的一个静态成员来完成,这样就实现了延迟初始化,也是懒汉式写法
//利用嵌套内部类
public sealed class Singleton5
{
    private Singleton5()
    {
        Debug.Log("执行了 Singleton5 构造函数");
    }

    public static Singleton5 Instance
    {
        get
        {
            return Temp.m_Singleton2;
        }
    }

    public void Excute()
    {
        Debug.Log("执行了 Singleton5");
    }

    class Temp
    {
        private Temp()
        {

        }

        internal static readonly Singleton5 m_Singleton2 = new Singleton5();
    }
}

总结:推荐第4、5种写法