zoukankan      html  css  js  c++  java
  • 如果你想让继承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;
          }
      }
    }

  • 相关阅读:
    2014年寒假学习规划
    二十进制数的加法--【英雄会】
    使用IBM SVC构建vSphere存储间集群
    游戏服务器学习笔记 2———— 准备工作
    php判断正常访问和外部访问
    游戏服务器学习笔记 3———— firefly 的代码结构,逻辑
    数学基础知识 ——(1)高等数学
    动态内存与智能指针
    Numpy(4)—— 保存和导入文件
    Numpy(3)—— 线性代数相关函数
  • 原文地址:https://www.cnblogs.com/yushui/p/4155139.html
Copyright © 2011-2022 走看看