如果你想让继承MonoBehaviour的类变成Singleten

单例是指只有一个实例的类

通常创建单例的方法是

using System; 
public class Singleton 
{ 
   private static Singleton instance; 
   private Singleton() {} 
   public static Singleton Instance 
   { 
      get  
      { 
         if (instance == null) 
         { 
            instance = new Singleton(); 
         } 
         return instance; 
      } 
   } 
}
但是由于MonoBehaviour中不能用new,不能从一个构造函数初始化,所以上面这段代码要改写成
using System;
public class Singleton :MonoBehavior
{
   private static Singleton instance;
   public static Singleton Instance
   {
      return instance;
   }
void Awake()
{
instance = this;
}
}
现在回过头来看通常方法有什么优点和缺点

优点
1.由于实例是在Instance属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化),即使它可能引入不想要的依赖性。
2.直到对象要求产生一个实例才执行实例化;这种方法称为“懒实例化”。懒实例化避免了在应用程序启动时实例化不必要的singleton。

缺点
在多线程环境下是不安全的。如果执行过程的不同线程同时进入Instance属性方法,那么可能会创建多个Singleton对象实例。

解决方法——静态初始化
public sealed class Singleton 
{ 
   private static readonly Singleton instance = new Singleton(); 
   private Singleton(){} 
   public static Singleton Instance 
   { 
      get  
      { 
         return instance;  
      } 
   } 
} 
在此策略中,将在第一次引用类的任何成员时创建实例。
sealed阻止派生。
变量标记为readonly,意味着只能在静态初始化期间或在类构造函数中分配变量。

多线程Singleton

下面的实现仅允许一个线程在尚未创建 Singleton 实例的情况下进入关键区域(该区域由 lock 块标识)。

using System; 
public sealed class Singleton 
{ 
   private static volatile Singleton instance; 
   private static object syncRoot = new Object(); 
   private Singleton() {} 
   public static Singleton Instance 
   { 
      get  
      { 
         if (instance == null)  
         { 
            lock (syncRoot)  
            { 
               if (instance == null)  
                  instance = new Singleton(); 
            } 
         } 
         return instance; 
      } 
   } 
} 
http://msdn.microsoft.com/zh-cn/library/ff650316.aspx

下面是一个不使用Awake实现单例化并继承MonoBehavior的例子

using UnityEngine;
using System.Collections;

/// <summary>
/// MONOBEHAVIOR PSEUDO SINGLETON ABSTRACT CLASS
/// usage    : best is to be attached to a gameobject but if not that is ok,
///      : this will create one on first access
/// example  : '''public sealed class MyClass : Singleton<MyClass> {'''
/// references   : http://tinyurl.com/d498g8c
///      : http://tinyurl.com/cc73a9h
///      : http://unifycommunity.com/wiki/index.php?title=Singleton
/// </summary>
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{

  private static T _instance = null;
         
  /// <summary>
  /// gets the instance of this Singleton
  /// use this for all instance calls:
  /// MyClass.Instance.MyMethod();
  /// or make your public methods static
  /// and have them use Instance
  /// </summary>
  public static T Instance {
      get {
          if (_instance == null) {
              _instance = (T)FindObjectOfType (typeof(T));
              if (_instance == null) {
                 
                  string goName = typeof(T).ToString ();         
                 
                  GameObject go = GameObject.Find (goName);
                  if (go == null) {
                      go = new GameObject ();
                      go.name = goName;
                  }
                 
                  _instance = go.AddComponent<T> ();                
              }
          }
          return _instance;
      }
  }
 
  /// <summary>
  /// for garbage collection
  /// </summary>
  public virtual void OnApplicationQuit ()
  {
      // release reference on exit
      _instance = null;
  }
 
  // in your child class you can implement Awake()
  // and add any initialization code you want such as
  // DontDestroyOnLoad(go);
  // if you want this to persist across loads
  // or if you want to set a parent object with SetParent()
 
  /// <summary>
  /// parent this to another gameobject by string
  /// call from Awake if you so desire
  /// </summary>
  protected void SetParent (string parentGOName)
  {
      if (parentGOName != null) {
          GameObject parentGO = GameObject.Find (parentGOName);
          if (parentGO == null) {
              parentGO = new GameObject ();
              parentGO.name = parentGOName;
          }
          this.transform.parent = parentGO.transform;
      }
  }
}

posted @ 2014-12-10 12:19  听雨歌楼上  阅读(232)  评论(0编辑  收藏  举报