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
这样就搞定了。。。
最后:
单例模式虽然好用,但是容易形成“单例癖”
所以,应该咋仔细设计和特定的前提之下,适当地采用单例模式