GoF中定义:
“确认类只有一个对象,并提供一个全局的方法来获取这个对象”
使用单例模式的前提
它只能产生一个对象且不能够被继承
单例模式的优点:
提供方便获取唯一对象的方法
可以限制对象的产生数量
单例模式的缺点:
容易造成设计思考不周和过度使用的问题
违反了“开-闭原则”(OCP)
using System.Collections; using UnityEngine; public class Test : MonoBehaviour { public static Test _instance; // Use this for initialization private void Start() { _instance = this; } // Update is called once per frame private void Update() { } }
这两行代码就是一个最简单的静态变量
可以看到,_instance是静态变量,因此可以在其他调用
而_instance的类型又是类本身
可以看做此类的一个实例
这么一来,也就是可以在其他脚本中通过_instance调用Text脚本中的任何变量和方法
在其他脚本中只需要使用此代码:
Text._instance.XXX
是不是很方便呢
当然,当需要使用单例模式的脚本太多
在每个脚本里都写这样的代码就有点违背代码简洁的初衷了
所以呢,我们可以写一个单例模式的基类
当某个脚本需要使用单例模式时,只需要继承这个脚本就可以了
using System; using System.Collections; using System.Collections.Generic; public class Singleton : MonoBehaviour { private static GameObject m_Container = null; private static string m_Name = "Singleton"; private static Dictionary<string, object> m_SingletonMap = new Dictionary<string, object>(); private static bool m_IsDestroying = false; public static bool IsDestroying { get { return m_IsDestroying; } } public static bool IsCreatedInstance(string Name) { if(m_Container == null) { return false; } if (m_SingletonMap!=null && m_SingletonMap.ContainsKey(Name)) { return true; } return false; } public static object getInstance (string Name) { if(m_Container == null) { Debug.Log("Create Singleton."); m_Container = new GameObject (); m_Container.name = m_Name; m_Container.AddComponent (typeof(Singleton)); } if (!m_SingletonMap.ContainsKey(Name)) { if(System.Type.GetType(Name) != null) { m_SingletonMap.Add(Name, m_Container.AddComponent (System.Type.GetType(Name))); } else { Debug.LogWarning("Singleton Type ERROR! (" + Name + ")"); } } return m_SingletonMap[Name]; } public static void RemoveInstance(string Name) { if (m_Container != null && m_SingletonMap.ContainsKey(Name)) { UnityEngine.Object.Destroy((UnityEngine.Object)(m_SingletonMap[Name])); m_SingletonMap.Remove(Name); Debug.LogWarning("Singleton REMOVE! (" + Name + ")"); } } void Awake () { Debug.Log("Awake Singleton."); DontDestroyOnLoad (gameObject); } void Start() { Debug.Log("Start Singleton."); } void Update() { } void OnApplicationQuit() { Debug.Log("Destroy Singleton"); if(m_Container != null) { GameObject.Destroy(m_Container); m_Container = null; m_IsDestroying = true; } } }
例如,添加这个脚本后,我们要调用Test脚本的属性:
Test text = Singleton.getInstance(“Text”) as Text;
text.XXX
这样就搞定了。。。
最后:
单例模式虽然好用,但是容易形成“单例癖”
所以,应该咋仔细设计和特定的前提之下,适当地采用单例模式