单例模式在Unity中的应⽤
起因:每个游戏场景中都会有许多的游戏对象,⽽各个游戏场景之间也是同等的关系。如何去管理它们,是我们要解决的问题。
场景中各脚本间的直接访问,会在各脚本间形成⼀个巨⼤⽽⼜混乱的⽹络,这给以后代码的维护带来了极⼤的困难。为了避免这种因交互访问⽽带来的过度耦合情况,我们取消掉场景中各脚本间的直接交互,取⽽代之的是,让所有脚本都只与场景中的⼀个特定脚本交互。
java单例模式双重锁在刚开始使⽤这种⽅法时,⾃⼰声明了⼀个场景中的全局脚本,然后把场景中所有其他需要交互的脚本声明为其成员,⼀旦脚本间要发⽣交互,就在脚本中声明⼀个全局脚本的对象,然后通过这个对象去访问其他的脚本,从⽽把直接交互变成了间接交互。这样做确实解决了脚本之间直接访问带来的⾼耦合度问题,但是在每个脚本中都要保存⼀个全局脚本的对象,这显然有些不太合适,浪费了资源。为了进⼀步解决这个问题,引⼊了单例模式的应⽤。
单例模式的定义是:保证⼀个类只有⼀个实例,并且提供⼀个访问它的全局访问点。单例对象的类必须保证只有⼀个实例存在。在我们的场景中,全局脚本的对象只会创建⼀次,保证单例,然后它(全局单例类)提供给各个脚本访问单例对象的⽅法,并且所有其他脚本的公共数据都会存储在全局单例脚本中。
private static GloSingleton _globalSingleton;
声明全局单例类⾃⾝类型的静态私有成员变量,作为单例对象使⽤。
public static GloSingletonGetSingleton() { …}
提供获取单例对象的类的静态⽅法。任何对单例对象的访问都要通过该⽅法来获取。
if (null ==_globalSingleton) {
lock(_globalSingleton) {
if(null == _globalSingleton) {
_globalSingleton=
(GloSingleton)GameObject.FindObjectOfType(typeof(GloSingleton));
}
}
}
单例模式的使⽤在多线程并发的情况下必须⼩⼼谨慎。因为当唯⼀实例尚未创建时,如果有两个线程同时调⽤创建⽅法,那么它们同时没有检测到唯⼀实例的存在,从⽽同时各⾃会创建⼀个实例,这违背了单例模式中实例唯⼀的原则。解决这个问题的办法是为指⽰类是否已经实例化的变量提供⼀个互斥锁。
如我们的代码所⽰,在⽅法内部,⾸先判断单例对象是否为空,为空的话说明单例对象还没有创建,需要实例化⼀个。反之直接返回单例对象。在准备⾸次创建单例对象时,设置了⼀个互斥锁。⽬的是为了在多线程并发的情况下也能保证单例。相关内容请参看我转载的另⼀篇博⽂《》。互斥锁中的判空检测同样是为了保证单例⽽设的。如果没有⼆次的检测,当线程A进⼊lock代码块中,线程B等待时,刚开始单例对象还没有创建,线程A执⾏完毕离开lock代码块后,单例对象已被创建完毕,⽽此时原本等待的线程B会进到lock代码块中,再次创建单例对象,因此单例被破坏。⼆次检测则避免了这种情况的发⽣。当线程A从lock中离开时,单例对象已经存在,线程B进⼊lock,便不会再执⾏创建单例对象的代码了。
这种实现⽅式即遵守了单例模式,⼜不必在每次获取单例对象时进⾏互斥锁的判断,提⾼了效率。因为⾃⼰对单例模式的理解⽐较简单,若⼤家有更好的实现⽅法,欢迎交流讨论。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论