单例模式在Unity中的应用
起因:每个游戏场景中都会有许多的游戏对象,而各个游戏场景之间也是同等的关系。如何去管理它们,是我们要解决的问题。
场景中各脚本间的直接访问,会在各脚本间形成一个巨大而又混乱的网络,这给以后代码的维护带来了极大的困难。为了避免这种因交互访问而带来的过度耦合情况,我们取消掉场景中各脚本间的直接交互,取而代之的是,让所有脚本都只与场景中的一个特定脚本交互。
在刚开始使用这种方法时,自己声明了一个场景中的全局脚本,然后把场景中所有其他需要交互的脚本声明为其成员,一旦脚本间要发生交互,就在脚本中声明一个全局脚本的对象,然后通过这个对象去访问其他的脚本,从而把直接交互变成了间接交互。这样做确实解决了脚本之间直接访问带来的高耦合度问题,但是在每个脚本中都要保存一个全局脚本的对象,这显然有些不太合适,浪费了资源。为了进一步解决这个问题,引入了单例模式的应用。
单例模式的定义是:保证一个类只有一个实例,并且提供一个访问它的全局访问点。单例对象的类必须保证只有一个实例存在。在我们的场景中,全局脚本的对象只会创建一次,保证单例,然后它(全局单例类)提供给各个脚本访问单例对象的方法,并且所有其他脚本的公共数据都会存储在全局单例脚本中。
private static GloSingleton _globalSingleton;
声明全局单例类自身类型的静态私有成员变量,作为单例对象使用。
public static GloSingletonGetSingleton() { …}
提供获取单例对象的类的静态方法。任何对单例对象的访问都要通过该方法来获取。
if (null ==_globalSingleton) {
lock(_globalSingleton) {
if(null == _globalSingleton) {
_globalSingleton=
(GloSingleton)GameObject.FindObjectOfType(typeof(GloSingleton));
}
}
}
单例模式的使用在多线程并发的情况下必须小心谨慎。因为当唯一实例尚未创建时,如果有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自会创建一个实例,这违背了单例模式中实例唯一的原则。解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁。
如我们的代码所示,在方法内部,首先判断单例对象是否为空,为空的话说明单例对象还没有创建,需要实例化一个。反之直接返回单例对象。在准备首次创建单例对象时,设置了一个互斥锁。目的是为了在多线程并发的情况下也能保证单例。相关内容请参看我转载的另一篇博文《C#中的lock关键字》。互斥锁中的判空检测同样是为了保证单例而设的。如果没有二次的检测,当线程A进入lock代码块中,线程B等待时,刚开始单例对象还没有创建,线程A执行完毕离开lock代码块后,单例对象已被创建完毕,而此时原本等待的线程B会进到lock代码块中,再次创建单例对象,因此单例被破坏。二次检测则避免了这种情况的发生。当线程A从lock中离开时,单例对象已经存在,线程B进入lock,便不会再执行创建单例对象的代码了。
这种实现方式即遵守了单例模式,又不必在每次获取单例对象时进行互斥锁的判断,提高了效率。因为自己对单例模式的理解比较简单,若大家有更好的实现方法,欢迎交流讨论。
单例模式在Unity中的应用的更多相关文章
- Unity中C#单例模式使用总结
一.单例模式优点 单例模式核心在于对于某个单例类,在系统中同时只存在唯一一个实例,并且该实例容易被外界所访问: 意味着在内存中,只存在一个实例,减少了内存开销: 二.单例模式特点 只存在唯一一个实例: ...
- 【Unity3D基础教程】给初学者看的Unity教程(七):在Unity中构建健壮的单例模式(Singleton)
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点推荐.谢谢! 该博客中的代码均出自我的开源项目 : 迷你微信 ...
- MonoSingleton——Unity中的单例模式
Unity中有很多特别的类需要以单例模式呈现,比如全局的UI管理类,各种缓存池,以及新手导航类等等.而Unity中,因为所有继承自Monobehaviour的脚本在实现的时候都是单线程的,所以像网上流 ...
- Unity中的万能对象池
本文为博主原创文章,欢迎转载.请保留博主链接http://blog.csdn.net/andrewfan Unity编程标准导引-3.4 Unity中的万能对象池 本节通过一个简单的射击子弹的示例来介 ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则
作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的22条准则
引言 原则1尽可能地使用属性而不是可直接访问的数据成员 原则2偏向于使用运行时常量而不是编译时常量 原则3 推荐使用is 或as操作符而不是强制类型转换 原则4 推荐使用条件属性而不是if条件编译 原 ...
- 【转】Effective C#观后感之提高Unity中C#代码质量的21条准则
转自:http://blog.csdn.net/swj524152416/article/details/75418162 我们知道,在C++领域,作为进阶阅读材料,必看的书是<Effectiv ...
- Unity编程标准导引-3.4 Unity中的对象池
本文为博主原创文章,欢迎转载.请保留博主链接http://blog.csdn.net/andrewfan Unity编程标准导引-3.4 Unity中的对象池 本节通过一个简单的射击子弹的示例来介绍T ...
- Unity中使用Attribute
Attribute是c#的语言特性 msdn说明如下: The Attribute class associates predefined system information or user-def ...
随机推荐
- Windows 服务卸载之后 重新安装提示 “指定的服务已标记为删除”
背景: 将一个项目做成一个windows服务,在调试的时候,需要卸载.安装该服务,但提示下面的错误:“指定的服务已标记为删除”,进入服务管理界面,启动自己注册的服务,无法手动更改成启用模 ...
- [JS][jQuery]remove()与 empty()的差别
要用到移除指定元素的时候,发现empty()与remove([expr])都能够用来实现.可细致观察效果的话就能够发现. empty()是仅仅移除了 指定元素中的全部子节点.拿$("p&qu ...
- [RxJS] Combination operator: zip
CombineLatest and withLatestFrom are both AND-style combination operators. In this lesson, we will l ...
- 轻量级的原型设计工具-Axure RP
1. 软件下载地址: http://www.downxia.com/downinfo/25742.html 这个版本不需要注册码,不需要安装,存绿色版. 2. 基本介绍教程: http://wenku ...
- struts2 convention-plugin实现零配置
零配置并不是没有配置,而是通过约定大于配置的方式,大量通过约定来调度页面的跳转而使得配置大大减少.使得Action等配置不必写在Struts.xml中. convention-plugin的约定 1. ...
- .NET Core的介绍
ASP.NET5应用程序默认使用.net core来构建应用程序,.net core是一个小的,优化过的.net运行时应用程序. 1. 什么是的.NET Core .NET Core 5 是一由模块化 ...
- c#迭代算法
//用迭代算法算出第m个值 //1,1,2,3,5,8...; //{1,0+1,1+1,1+2,2+3 ,3+5} static void Main(string[] arg ...
- Sql server 数据库中,纯SQL语句查询、执行 单引号问题。
在默认值情况下, select 'abc',Titile from tb_Name; ---输出内容 是abc: 如果想输出 单引号 'abc,需要使用select '''abc',Titile f ...
- 无软驱加载raid驱动安装windows2003及其他微软操作系统
[转载]http://blog.zol.com.cn/2650/article_2649199.html [另一篇]http://www.blue1000.com/bkhtml/c159/2013-0 ...
- Scanner中next()和nextline()读取字符串方法和区别
在实现字符窗口的输入时,我个人更喜欢选择使用扫描器Scanner,它操作起来比较简单.在写作业的过程中,我发现用Scanner实现字符串的输入有两种方法,一种是next(),一种nextLine(), ...