1. 程式人生 > >C#單例與繼承MonoBehaviour的單例

C#單例與繼承MonoBehaviour的單例

單例模式是我們最常用的一種設計模式。

主要優點:

1、提供了對唯一例項的受控訪問。

2、由於在系統記憶體中只存在一個物件,因此可以節約系統資源,對於一些需要頻繁建立和銷燬的物件單例模式無疑可以提高系統的效能。

3、允許可變數目的例項。

主要缺點:

1、由於單利模式中沒有抽象層,因此單例類的擴充套件有很大的困難。

2、單例類的職責過重,在一定程度上違背了“單一職責原則”。

3、濫用單例將帶來一些負面問題,如為了節省資源將資料庫連線池物件設計為的單例類,可能會導致共享連線池物件的程式過多而出現連線池溢位;如果例項化的物件長時間不被利用,系統會認為是垃圾而被回收,這將導致物件狀態的丟失。


首先是普通的C#單例模式

public abstract class CSharpSingletion<T> where T : new() {  
  
    private static T instance;  
    public static T Instance  
    {  
        get  
        {  
            if (instance == null)  
            {  
                instance = new T();  
            }  
            return instance;  
        }  
    }  
  
}
using UnityEngine;  
using System.Collections;  
  
public class AudioSingletion : CSharpSingletion<AudioSingletion> {  
  
    public int i = 1;  
}  

這裡使用了範型類約束,當我們需要使用單例類時繼承這個單例類就可以,這樣就可以提高程式碼的複用性。

接下來是Unity中繼承MonoBehaviour的單例型別,這裡做法和第一種類似,同樣使用繼承單例類的方法來實現統一管理。

using UnityEngine;
using System.Collections;

public class MonoSingletion<T> : MonoBehaviour where T :MonoBehaviour{

    private static string MonoSingletionName = "MonoSingletionRoot";
    private static GameObject MonoSingletionRoot;
    private static T instance;

    public static T Instance
    {
        get
        {
            if (MonoSingletionRoot==null)//如果是第一次呼叫單例型別就查詢所有單例類的總結點
            {
                MonoSingletionRoot = GameObject.Find(MonoSingletionName);
                if (MonoSingletionRoot==null)//如果沒有找到則建立一個所有繼承MonoBehaviour單例類的節點
                {
                    MonoSingletionRoot = new GameObject();
                    MonoSingletionRoot.name = MonoSingletionName;
                    DontDestroyOnLoad(MonoSingletionRoot);//防止被銷燬
                }
            }
            if (instance == null)//為空表示第一次獲取當前單例類
            {
                instance = MonoSingletionRoot.GetComponent<T>();
                if (instance == null)//如果當前要呼叫的單例類不存在則新增一個
                {
                    instance = MonoSingletionRoot.AddComponent<T>();
                }
            }
            return instance;
        }
    }

}
之後如果需要使用繼承了MonoBehaviour的單例型別只需要繼承MonoSingletion就可以
using UnityEngine;
using System.Collections;

public class MusicSingletion : MonoSingletion<MusicSingletion> {

    public void Show()
    {
        Debug.Log("Play Music");
    }
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	}
}

使用時只需要在其他地方呼叫 MusicSingletion.Instance.Show();就可以