Unity单例模式

145 阅读3分钟

设计模式简介

1.解决共通的问题

2.归纳相同的解决方案

3.类结构和组装方式

4.高复用度与组合使用

单例模式

1.what

单例模式:
    该模式只涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。该类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化类对象。
特点:
    单例类只能有一个实例;
    单例类必须自己创建自己的唯一实例;
    单例类必须给所有的其它对象提供这一实例;
    可以快速获取实例对象提供的方法或服务;
    适合游戏场景中单一功能的管理器。
    

2.when

使用场景:
    开发时需要控制实例数目,节省系统资源时。比如UI管理器、声音管理器、网络管理器等,有且只有一个实例,有且需要一个实例。

3.how

{
    //第一种方式
      public static Singleton _instance;
      private void Awake()
      {
          _instance = this;
      }
   //单例提供的公共方法
      public void SayHello()
      {
          Debug.LogError("I am" + name);
      }
   //缺点:这种方式必须在场景中创建挂载该单例组件的游戏物体,否者会出现空引用的错误。
public class Singleton:MonoBehaviour
//第二种方式
       static Singleton instance;
       public static Singleton Instance
       {
           get
           {
               if (instance == null)
               {
                   instance = FindObjectOfType<Singleton>();
               }
               if (instance == null)
               {
                   GameObject obj = new GameObject();
                   obj.AddComponent<Singleton>();
                   instance = obj.GetComponent<Singleton>();
               }
               return instance;
           }
       }
//优点:弥补了第一种单例模式的不足,但是复用性不够

当我们使用线程的时候,效率最高的方式当然是异步,即个个线程同时运行,其间互不依赖和等待。当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被同一个线程操作,以确保每个操作都是有效即时的,也即保证其操作的原子性。

lock是C#中最常用的同步方式,格式为lock(objectA){codeB} 。
lock(objectA){codeB}表示意义:
1. objectA被lock了吗?没有则由我来lock,否则一直等待,直至objectA被释放。  
2. lock以后在执行codeB的期间其他线程不能调用codeB,也不能使用objectA。  
3. 执行完codeB之后释放objectA,并且codeB可以被其他线程访问。
public class WeiHaiSingleTon<T> : MonoBehaviour 
    where T : Component
{
    private static  volatile T _instance;

    //设置静态锁
    private static object _instanceLock = new object();
    public static T Instance
    {
        get 
        {
            if (_instance == null)
            {
                
                _instance = FindObjectOfType(typeof(T)) as T;
                lock (_instanceLock)
                {
                    if (_instance == null)
                    {
                        GameObject obj = new GameObject();
                        //隐藏实例化的对象
                        obj.hideFlags = HideFlags.HideAndDontSave;
                        _instance = obj.AddComponent<T>();
                        
                    }
                }
            }
            return _instance;
        }
    }
}

该ObjObjHideOrShowManager继承了WeiHaiSingleTon,间接地实现了单例模式,该单例模式为其它类提供了ShowNWall、HideNWall、ShowNBorder、HideNBorder、ShowBWall、HideBBorder、HideBWall、ShowBBorder、HideAllWallsAndFlickBorder等9种服务,其他类可以通过ObjHideOrShowManager.Instance.服务名调用服务。

public class ObjHideOrShowManager : WeiHaiSingleTon<ObjHideOrShowManager>
{
    private GameObject weihai_n_walls;
    private GameObject weihai_n_FlickBorder;
    private GameObject weihai_b_walls;
    private GameObject weihai_b_FlickBorder;

    private void Awake()
    {
        weihai_n_walls = GameObject.Find("weihai_n_walls");
        weihai_n_FlickBorder = GameObject.Find("weihai_n_FlickBorder");
        weihai_b_walls = GameObject.Find("weihai_b_walls");
        weihai_b_FlickBorder = GameObject.Find("weihai_b_FlickBorder");
    }

    #region Hide area-edge or area-num
    public void ShowNWall()
    { 
        weihai_n_walls.SetActive(true);
    }

    public void HideNWall()
    { 
        weihai_n_walls.SetActive(false);
    }

    public void ShowNBorder()
    { 
        weihai_n_FlickBorder.SetActive(true);
    }

    public void HideNBorder()
    {
        weihai_n_FlickBorder.SetActive(false);
    }

    public void ShowBWall()
    {
        weihai_b_walls.SetActive(true);
    }

    public void HideBWall()
    {
        weihai_b_walls.SetActive(false);
    }

    public void ShowBBorder()
    {
        weihai_b_FlickBorder.SetActive(true);
    }

    public void HideBBorder()
    {
        weihai_b_FlickBorder.SetActive(false);
    }

    public void HideAllWallsAndFlickBorder()
    {
        weihai_b_FlickBorder.SetActive(false);
        weihai_b_walls.SetActive(false);
        weihai_n_walls.SetActive(false);
        weihai_n_FlickBorder.SetActive(false);
    }
    #endregion
}