unity3d中的单例模式

单例模式(singleton pattern)大家都不陌生,今天主要是和大家探讨一下单例模式在unity中的实现,比起一般的单例,unity中有些他的特点。

最普通的单例:(样式一)

复制代码
public class Singleton
{
    static Singleton instance;
  
    public static Singleton Instance {
        get {
            if (instance == null) {
                instance = new Singleton ();
            }
            return instance;
        }
    }
}
复制代码

unity单例模式二:

但是unity的所有脚本都必须挂在一个gameobject上,否则无法执行,你这个单例中若只是一些数据,那倒没关系,但我相信绝大多数单例模式都不会只包含数据,若只要实现包含数据的功能,用全局静态变量就行了,说到这里加一句,有些盆友喜欢用单例脚本当做全局脚本来用,那其实是违背单例模式的初衷的…
好,我们来实现以下挂到gameobject的单例(模式二):

复制代码
public class UnitySingleton : MonoBehaviour
{
  static UnitySingleton instance;
  
  public static UnitySingleton Instance {
          get {
                if (instance == null)
                 {
                    GameObject obj = new GameObject (); 
                    instance = obj.AddComponent (typeof(UnitySingleton));
                }
                 return instance;
             }
 
  }
}
复制代码

unity单例模式三:

那如果我的游戏里有很多单例脚本,每个脚本都这么写岂不是很麻烦?岂不是很违背oo思想?_,那我们来设计一个泛型类:

复制代码
public class UnitySingleton<T> : MonoBehaviour
    where T : Component
{
    private static T _instance;
    public static T Instance {
        get {
            if (_instance == null) {
                instance = FindObjectOfType (typeof(T)) as T;
                if (_instance == null) {
                    GameObject obj = new GameObject ();
                    obj.hideFlags = HideFlags.HideAndDontSave;//隐藏实例化的new game object,下同
                    _instance = obj.AddComponent (typeof(T));
                }
            }
            return _instance;
        }
    }
}
复制代码

这样一来,场景中需要单例化的脚本只要简单的继承这个类就可以了

public class Manager : UnitySingleton<Manager>
{
public string testText = "hello Sinngleton!";
}

manager单例脚本将在第一次实例化时自动创建,当然,你是看不到他的呵呵,但是底部的debuglog出卖了他…:

public class SingletonTest : MonoBehaviour {
        // Use this for initialization
        void Start () {
                Debug.Log(Manager.Instance.testText);
        }
}

unity单例模式四:

最后一个问题就是,我希望我的所有单例脚本在场景变化后依然存在,那自然是用DontDestroyOnLoad,直接上脚本:

复制代码
using UnityEngine;
public class UnitySingleton<T> : MonoBehaviour
        where T:Component {
        private static T _instance;
        public static T Instance        {
                get{
                        if(_instance == null){
                                _instance = FindObjectOfType(typeof(T)) as T;
                                if(_instance == null){
                                        GameObject obj = new GameObject ();
                                        //obj.hideFlags = HideFlags.DontSave;
                                        obj.hideFlags = HideFlags.HideAndDontSave;
                                        _instance =(T) obj.AddComponent(typeof(T));
                                }
                        }
                        return _instance;
                }
        }
        public virtual void Awake()
        {
                DontDestroyOnLoad(this.gameObject);
                if(_instance == null){
                        _instance = this as T;
                }
                else{
                        Destroy(gameObject);
                }
        }
}
复制代码

至此,所有单例模式已经全部探讨完了,单例模式是最简单的设计模式,概念上没什么难懂的,只不过在unity中实现起来需要注意一下,

 

单例模式的作用:

这一模式的目的是使得类的一个对象成为系统中的唯一实例。

 

单例模式也是一种比较常见的设计模式,它到底能带给我们什么好处呢?其实无非是三个方面的作用:

第一、控制资源的使用,通过线程同步来控制资源的并发访问;

第二、控制实例产生的数量,达到节约资源的目的。

第三、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。

 

单例模式的实现方式:懒汉单例类和饿汉单例类

· 懒汉单例类

它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。

懒汉模式只在外部对象第一次请求实例的时候才去创建。

· 饿汉式单例

该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。

我们对比一下懒汉模式和饿汉模式的优缺点:

懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。

饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。

这两种模式对于初始化较快,占用资源少的轻量级对象来说,没有多大的性能差异。但是对于初始化慢,占用资源多的重量级对象来说,就会有比较明显的差别了。所以,对重量级对象应用饿汉模式,类加载时速度慢,但运行时速度快;懒汉模式则与之相反,类加载时速度快,但运行时第一次获得对象的速度慢。

数据库连接池属于重量级资源,一个应用中只需要保留一份即可,既节省了资源又方便管理。所以数据库连接池采用单例模式进行设计会是一个非常好的选择。

实际上,配置信息类、管理类、控制类、门面类、代理类通常被设计为单例类。像Java的Struts、Spring框架,.Net的Spring.Net框架,以及Php的Zend框架都大量使用了单例模式。

 

posted @   Domefy  阅读(660)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
历史上的今天:
2019-10-20 菜鸟学习初级教程-----强烈推荐(看完后成黑客拉)
点击右上角即可分享
微信分享提示