【Unity3D与23种设计模式】单例模式(Singleton)

 

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

这样就搞定了。。。

 

最后:

单例模式虽然好用,但是容易形成“单例癖”

所以,应该咋仔细设计和特定的前提之下,适当地采用单例模式

posted on 2017-07-14 15:49  Lumious  阅读(652)  评论(0编辑  收藏  举报

导航