当前位置: 首页 > news >正文

Unity单例模式基类全解析

目录

不继承MonoBehaviour的单例模式基类

继承MonoBehaviour的单例模式基类

挂载式的继承Mono的单例模式基类

自动挂载式的继承Mono的单例模式基类

解决构造函数带来的安全问题

解决重复挂载带来的安全问题

解决多线程带来的安全问题

是否加锁问题指什么?

解决多线程并发带来的问题


不继承MonoBehaviour的单例模式基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 单例模式基类 主要目的是避免代码的冗余 方便我们实现单例模式的类
/// </summary>
/// <typeparam name="T"></typeparam>
public class BaseManager<T> where T : class,new()
{private static T instance;//属性的方式public static T Instance{get {if(instance == null)instance = new T();return instance;}}//方法的方式public static T GetInstance(){if (instance == null)instance = new T();return instance;}
}
继承MonoBehaviour的单例模式基类
挂载式的继承Mono的单例模式基类

容易破坏单例模式的唯一性

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 挂载式的继承Mono的单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T Instance{get{ return instance;}}protected virtual void Awake(){instance = this as T;}
}
自动挂载式的继承Mono的单例模式基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 自动挂载式的继承Mono的单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T Instance{ get {if (instance == null){//动态创建 动态挂载GameObject gameObject = new GameObject(typeof(T).Name);instance = gameObject.AddComponent<T>();//过场景不移除 保证整个游戏声明周期只有一份DontDestroyOnLoad(gameObject);}return instance; }}}
解决构造函数带来的安全问题

1.父类变为抽象类

2.规定继承单例模式基类的类必须显示实现私有无参构造函数

3.在基类中通过反射来调用私有无参构造函数实例化对象

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;/// <summary>
/// 单例模式基类 主要目的是避免代码的冗余 方便我们实现单例模式的类
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseManager<T> where T : class
{private static T instance;//属性的方式public static T Instance{get {if (instance == null){ //instance = Activator.CreateInstance(typeof(T),true) as T;Type type = typeof(T);//利用反射得到无参私有的构造函数 来用于对象的实例化ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic,null,Type.EmptyTypes,null);if (constructor != null)instance = constructor.Invoke(null) as T;elseDebug.LogError("没有得到对应的无参私有的构造函数");}return instance;}}//方法的方式public static T GetInstance(){if (instance == null){Type type = typeof(T);//利用反射得到无参私有的构造函数 来用于对象的实例化ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null,Type.EmptyTypes,null);if (constructor != null)instance = constructor.Invoke(null) as T;elseDebug.LogError("没有得到对应的无参私有的构造函数");}return instance;}
}
解决重复挂载带来的安全问题

解决重复挂载带来的安全问题

对于挂载式的单例模式脚本

1.同一个对象的重复挂载 ,为脚本添加特性[DisallowMultipleComponent]

//不允许在同一个对象上挂载多个相同的脚本
[DisallowMultipleComponent]
public class lessonTest : SingletonMono<lessonTest>
{public void TestLog(){print("lessonTest");}
}

2.修改代码逻辑, 判断如果存在对象,移除脚本

对于自动挂载式的单例模式脚本,制定使用规则,不允许手动挂载或代码添加

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 挂载式的继承Mono的单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T Instance{get{ return instance;}}protected virtual void Awake(){//已经存在一个对应的单例模式对象了 不需要再有一个if (instance != null){Destroy(this);return;}instance = this as T;//我们挂载继承该单例模式基类的脚本后,依附的对象过场景时就不会被移除//就可以保证在游戏的整个生命周期中都存在DontDestroyOnLoad(this.gameObject);}
}
解决多线程带来的安全问题
是否加锁问题指什么?

如果程序当中存在多线程 ,我们需要考虑当多个线程同时访问同一个内存空间时出现的问题

如果不加以控制,可能会导致数据出错 ,我们一般称这种问题为多线程并发问题,指多线程对共享数据的并发访问和操作。

而一般解决该问题的方式,就是通过C#中的lock关键字进行加锁,我们需要考虑我们的单例模式对象们是否需要加锁(lock)

lock 的原理保证了在任何时刻只有一个线程能够执行被锁保护的代码块 ,从而防止多个线程同时访问或修改共享资源,确保线程安全

解决多线程并发带来的问题

1.不继承MonoBehaviour的单例模式 ,建议加锁,避免以后使用多线程时出现并发问题, 比如在处理网络通讯模块、复杂算法模块时,经常会进行多线程并发处理

2.继承MonoBehaviour的单例模式, 可加可不加,但是建议不加。

因为Unity中的机制是,Unity主线程中处理的一些对象(如GameObject、Transform等等),是不允许被其他多线程修改访问的,会直接报错 ,因此我们一般不会通过多线程去访问继承MonoBehaviour的相关对象,既然如何,就不会发生多线程并发问题

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;/// <summary>
/// 单例模式基类 主要目的是避免代码的冗余 方便我们实现单例模式的类
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseManager<T> where T : class
{private static T instance;//用于加锁的对象protected static readonly object lockObj = new object();//属性的方式public static T Instance{get {if (instance == null){lock (lockObj){if (instance == null){//instance = Activator.CreateInstance(typeof(T),true) as T;Type type = typeof(T);//利用反射得到无参私有的构造函数 来用于对象的实例化ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null,Type.EmptyTypes,null);if (constructor != null)instance = constructor.Invoke(null) as T;elseDebug.LogError("没有得到对应的无参私有的构造函数");}}}return instance;}}//方法的方式public static T GetInstance(){if (instance == null){lock (lockObj){if (instance == null){Type type = typeof(T);//利用反射得到无参私有的构造函数 来用于对象的实例化ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null,Type.EmptyTypes,null);if (constructor != null)instance = constructor.Invoke(null) as T;elseDebug.LogError("没有得到对应的无参私有的构造函数");}}}return instance;}
}
http://www.dtcms.com/a/528683.html

相关文章:

  • 餐饮行业做网站的数据ctoc网站有哪些
  • 深圳建设局网站投诉电话淄博网站建设优化公司
  • 久治县网站建设公司东莞人才网最新招聘信息
  • MySQL OCP认证、Oracle OCP认证
  • 深入探讨HarmonyOS中ListItem的滑动操作:从基础实现到高级分布式交互
  • Eclipse Uninstall Software
  • 广东南方通信建设有限公司官方网站合肥网站建设的价格
  • C语言<<超全.超重要>>知识点总结
  • 购物网站开发的业务需求分析做钢材什么网站好
  • Spring框架常用注解全面详解与技术实践
  • 机器学习三要素
  • synchronized锁优化与升级机制
  • 设计公司网站运营wordpress+编辑模板
  • URL下载网络资源
  • Spring Bean注解终极指南:从入门到精通
  • wordpress旅游类网站深圳哪里做网站
  • 【FPGA】38译码器板级验证
  • 初学JVM---什么是JVM
  • 企培内训APP开发案例:实现视频课程、考试与绩效考核一体化
  • 网站后台怎么上传图片产品wordpress不能搜索文章
  • 网站首页默认的文件名一般为云指官网
  • Kafka消费者在金融领域的深度实践:从交易处理到风险控制的完整架构
  • 使用阿里云效搭建个人maven私有仓库
  • Android Studio新手开发第三十一天
  • (四)Gradle 依赖树分析与依赖关系优化
  • Drogon: 一个开源的C++高性能Web框架
  • Java Stream 流:让数据处理更优雅的 “魔法管道“
  • 查看网站服务器ip受欢迎的购物网站建设
  • fpga实现音频预加重(pre-emphasis)滤波器
  • Rust中的Enum与Struct详解