先了解下单例设计模式:
单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
单例模式的要点有三个:
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
在下面的对象图中,有一个"单例对象",而"客户甲"、"客户乙"和"客户丙"是单例对象的三个客户对象。 可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。
cocos2d很好的利用了单例设计模式。
单例的好处是它可以在任何时间任何地点被任何类所调用。它接近于全局类的 作用,更像一个全局变量。如果你需要在任何地方都能用到某些数据或者方法, 单例是很好的选择。音频就是个很好的例子:因为任何一个类,不管是玩家, 敌人,菜单按钮,或是过场动画,都可能需要播放声效或者改变背景音乐。因 此,使用单例来播放音频是很好的选择。同样,如果存在全局的游戏状态,比 如说玩家军队的大小和每支部队排的数目,你可以把这些信息存到一个单例中, 把这些信息从一个关卡传到另一个关卡。
单例在程序生命周期中只被实例化一次,为此常用利用类的一个静态方法来生成和访问对象,cocos2d常通过share开头的方法来访问单例对象,而不是用alloc/iniit或者静态autorelease初始化,比如一下常用的方法
CCActionManager* sharedManager = [CCActionManager sharedManager];
CCDirector* sharedDirector = [CCDirector sharedDirector];
CCSpriteFrameCache* sharedCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCTextureCache* sharedTexCache = [CCTextureCache sharedTextureCache];
CCTouchDispatcher* sharedDispatcher = [CCTouchDispatcher sharedDispatcher];
CDAudioManager* sharedManager = [CDAudioManager sharedManager];
SimpleAudioEngine* sharedEngine = [SimpleAudioEngine sharedEngine];
CCDirector类实现单例方法
static CCDirector *_sharedDirector = nil; + (CCDirector *)sharedDirector { if (!_sharedDirector) { // // Default Director is DisplayLink // if( [ [CCDirector class] isEqual:[self class]] ) _sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init]; else _sharedDirector = [[self alloc] init]; } return _sharedDirector; }
单例也有不好的方法,本身很容易实现,在任何地方也可以被访问到,这就造成在不该用到的地方用上了,就会增加麻烦;
例如,你可能觉得你的游戏只有一个玩家对象,所以为什么就不能把玩家这个类变成单例呢?一切看起来都没有什么问题 –直到你认识到不管什么时候这个玩家进入下一个关卡,这个玩家不仅带着上一关卡的得分,而且还有上一关卡的最后一帧动画信息,健康值,和所有已经捡到的物品,并且由于他在离开上一关卡的时候还在“狂暴”状态下,在新关卡开始的时候,他还处于之前的状态中。
为了解决这个问题,你可能会在类里加入一个重置某些变量的方法。看起来问题解决了。但是当你在游戏代码中添加越来越多的功能以后,在转换关卡时,你需要维护的变量也会越来越多。最糟糕的是,某天你的朋友建议你为iPad版本增加个双人模式。但是你发现你的玩家类是个单例,在任何时候你只能有一个玩家对象存在!这可麻烦了:要么你要重写很多代码,或者只能放弃很酷的双人模式了。