cocos2d笔记——cocos2d的单例模式
cocos2d充分使用了单例设计模式,这里有必要提及它是因为它是经常是讨论热点。大体上说,一个singleton是一个类,它在应用使用期中仅仅实例化一次。为了确保如此,就要使用一个既创建又访问此对象实例的静态方法。因此,你不使用alloc/init或者静态自动释放初始化器(static autorelease initializer),而是使用以shared开通的方法来访问一个单例对象。这里有一些cocos2d最常用的单例方法,并告诉你怎么访问:
CCTextureCache* sharedTexCache = [CCTextureCache sharedTextureCache];
CDAudioManager* sharedManager = [CDAudioManager sharedManager];
上面的单例你可以任何时候在任何类的任何地方使用。这有点儿想全局类,就像全局变量。如果你有一组用在很多地方的数据和方法,单例就非常有用。音频是一个好例子,因为你任何类(无论是主角、敌人、菜单按钮、场景剪辑)都需要有呻吟效果,或者更换背景音乐。因此使用一个单例来播放声音就很有道理。类似的,如果你有全局游戏状态,可能是玩家军队的数量,或者每组军队的人数,你就需要用一个单例来存储这些信息,因此,你可以带着它从一关到另一关。实现一个单例非常直接,就像下面的代码所示,这段代码用最少篇幅通过单例方式实现了MyManager类。静态方法sharedManager授权访问单个MyManager实例。如果这个实例不存在,就会给以个MyManger实例分配内存并初始化,否则,就返回这个已存在的实例。
+(MyManager*) sharedManager {
if (sharedManager == nil) {
sharedManager = [[MyManager alloc] init];
}
return sharedManager;
}
不过单例模式也有差劲一面。因为他们易于使用和实现,并能从任何其他类访问,那就有在不该使用的地方出现的可能。
例如,你可能认为你只有一个player对象,那么为什么不把他作为单例呢?皆大欢喜,但是,你会意识到每当player从一关升级到另一关的时候,这个单例不仅保留着原有的分数,而且保留了他的最近动画状态、生命值以及一切带着的项目,甚至它会以狂暴模式开始新一关,只因为他离开上一关的时候这个模式是活动的。
为了修正此误,你就要添加一个方法在进另一关的时候去重置某些变量。到目前还好,但是当你在游戏中添加更多特性时,你就会停下来不得不添加和维护越来越多的变量。更糟糕的是,设想某天一个朋友建议你给iPad来一个双人模式的版本。但是,等等,你的player是单例,你在任何时候都只能是唯一的!这让你很头大:重构大量代码还是错失双人模式的大好机会?
你越依赖单例模式,你面临的问题就越多。在常见一个单例类前,一定要考虑好是否你真的需要这个类的唯一实例,是否后面会有修改。