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

Unity中常用的单例模式

程序员文章站 2024-03-12 19:49:08
...

基本单例

懒汉模式

用到时才创建的单例模式

//单例模式
//	懒汉	在使用时才创建
//	缺点:不适用于多线程
//	私有化构造函数
public class SingletonTest_Base
{
	private static SingletonTest_Base instance;
	public static SingletonTest_Base Instance
	{
		get
		{
			if (instance == null)
			{
				instance = new SingletonTest_Base();
			}
			return instance;
		}
	}

	private SingletonTest_Base(){}
}

饿汉模式

初始化时即创建的单例模式

//单例模式
//	饿汉	在编译时创建
//	优点:线程安全
//	缺点:实例常驻 占用内存 不能控制初始化顺序, 大量单例在程序开始时初始化,可能造成卡顿
public class SingletonTest_Inited
{
	private static SingletonTest_Inited instance = new SingletonTest_Inited();
	public static SingletonTest_Inited Instance
	{
		get
		{
			return instance;
		}
	}
	private SingletonTest_Inited(){}
}

线程安全的懒汉模式

加线程锁、二次检查及防止指令重排序

Tip:多核处理器会对运行CPU指令顺序重排优化,MemoryBarrier可以阻止指令重排

//单例模式
//	懒汉 
//	加线程锁 线程安全
public class SingletonTest_Lock
{
	private static readonly object lockObj = new object();
	private static SingletonTest_Lock instance;
	private static SingletonTest_Lock Instance
	{
		get
		{
			//为空时初始化
			if (instance == null)
			{
				//加锁
				lock (lockObj)
				{
					//再次检查
					if (instance == null)
					{
						var tmp= new SingletonTest_Lock();
                        // ensures that the instance is well initialized,
                        // and only then, it assigns the static variable.
						//官方文档是说Thread.MemoryBarrier(),
                        //保证之前的数据存取优先于MemoryBarrier执行,只有在多CPU下才需要使用
                        System.Threading.Thread.MemoryBarrier();
                        instance = tmp;
					}
				}
			}

			return instance;
		}
	}

	private SingletonTest_Lock(){}
}

范型单例

普通范型单例

范型基类


//单例范型
//  继承自该类的单例,可以通过instance获取实例
//  只有new约束之后才能new,但是new约束的话,继承自该类的子类不能有私有构造函数
//  所以这里的范型单例只是使用上约定的单例,并不能在语法上规定单例
public abstract class Singleton<T> where T : Singleton<T>, new()
{
	private static readonly object lockObj = new object();
    protected static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                    {
                        instance = new T();
                    }
                }
            }
            return instance;
        }
    }
}

单例子类

//子类
public class Manager: Singleton<Manager>
{
    // private Manager(){}  继承自new约束的范型,不能私有化构造函数
    public void Test() {}
}

调用测试

//调用
public class Client_Test
{
    public void Test()
    {
        //调用测试
        Manager.Instance.Test();

        //没有被约束的Manager类 可以被new出来新的实例
        Manager mgr = new Manager();
    }
}

用反射去创建实例的范型单例

范型基类

//用反射去创建实例的单例
public abstract class Singleton_R<T> where T : Singleton_R<T>
{
	private static readonly object lockObj = new object();
    protected static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                    {
                        //反射来创建实例
                        instance = (T) System.Activator.CreateInstance(typeof(T), true);
                    }
                }
            }
            return instance;
        }
    }
}

子类

//子类
public class Manager_R: Singleton_R<Manager_R>
{
    public void Test() {}

    //私有化构造函数
    private Manager_R(){}
}

调用

//调用
public class Client_Test_Ref
{
    public void Test()
    {
        Manager_R.Instance.Test();

        //构造函数被私有化而不能初始化
        // Manager_R mgrr = new Manager_R();
    }
}

Mono范型单例

基类


using UnityEngine;

//mono单例
//  只是使用方便
//  通过add依然可以创建出来对象
//  所以并不是语法严谨的单例
public abstract class MonoSingleton<T>: MonoBehaviour where T: MonoSingleton<T>
{
    private static object _lock = new object();
	protected static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                lock (_lock)
                {
                    if (instance == null)
                    {
                        instance = FindObjectOfType<T>();
                        if (instance == null)
                        {
                            string instanceName = typeof(T).Name;
                            GameObject instanceGO = GameObject.Find(instanceName);

                            if (instanceGO == null)
                            {
                                instanceGO = new GameObject(instanceName);
                            }

                            instance = instanceGO.AddComponent<T>();        //单例构造函数被私有化了 unity依然可以add
                            DontDestroyOnLoad(instanceGO);  //实例不被释放
                        }
                    }
                }
            }
            return instance;
        }
    }
}

子类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonoSingletonTest: MonoSingleton<MonoSingletonTest>
{
    //私有化构造函数
	//	这里只是不能被new出来,但依然可以通过unity的addcomponent去创建获取,没有意义
    private MonoSingletonTest(){}

	public void Test()
	{
		Debug.Log("test");
	}
}

调用

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonoSingleton_Client : MonoBehaviour 
{
	void Start () 
	{
		//调用
		MonoSingletonTest.Instance.Test();

		//另一个测试
		//	GameObject 被new出来就会出现在 Hierarchy 面板上
		GameObject obj1 = new GameObject("1");

		//	DontDestroy
		GameObject obj2 = new GameObject("2");
		DontDestroyOnLoad(obj2);

		//	这里会创建出两个
		//	一个名为3	另一个名为 3(Clone)
		GameObject obj3 = new GameObject("3");
		Instantiate(obj3);
	}
}