CCNotificationCenter是Cocos2dx实现的观察者模式,观察者模式也就是一个target可以注册多个观察者,当目标数据出现变化时,观察者可以知道做出什么样的变化(更新)。在MVC模式中一个Model可以注册多个Views,Model就是目标对象(target object),而View则是观察者,当Model中有数据变化时,要通知所有的View也相应的改变(更新)。
在需要监听的地方添加观察者,一般是View层监听数据变化之后刷新界面:
void __NotificationCenter::addObserver(Ref *target,SEL_CallFuncO selector,const std::string& name,Ref *sender)target表示回调函数的目标对象,selector是回调函数,可以接受一个CCObject类型的参数,name是观察者的类型,当该观察者监听到该类型的数据变化时,调用selector做相关操作。
CCNotificationCenter是目标对象,CCNotificationObserver是观察者,一个目标对象可以注册多个观察者,当目标对象的状态改变的时候,可以通知观察者对象作出相应的响应。这是标准的观察者模式的实现,但是CCNotificationCenter稍微有些许差别。
首先,CCNotificationCenter不是通过自身状态改变来通知观察者,而是通过显式地发送观察者感兴趣的消息(postNotification)来通知它们。
每一种消息类型可以对应多个观察者,比如游戏接受到玩家战斗力信息更改的消息,这个时候有3个观察者,分别为头像战力值、模型头顶战力值、VIP界面战力值,如果这三个UI同时存在,则这三个UI要同步刷新;
同时,每一个观察者也可以“观察”多个消息类型,比如VIP界面可能还有玩家HP值,Level值,那么VIP界面就可以注册一个观察HP值变化的观察者,一个观察Level值变化的观察者,当这些值发生变化的时候,观察者接收到监听消息通知VIP界面刷新。
其次,观察者定义相应的响应事件同消息类型关联,当某个地方触发postNotification来广播一个消息的时候,CCNotificationCenter会遍历所有的观察者,判断它们注册的消息类型是否匹配,如果匹配,则触发相应的注册响应事件。代码中postNotification函数的实现如下:
void __NotificationCenter::postNotification(const std::string& name,Ref *sender) { __Array* ObserversCopy = __Array::createWithCapacity(_observers->count()); ObserversCopy->addObjectsFromArray(_observers); Ref* obj = nullptr; CCARRAY_FOREACH(ObserversCopy,obj) { NotificationObserver* observer = static_cast<NotificationObserver*>(obj); if (!observer) continue; if (observer->getName() == name && (observer->getSender() == sender || observer->getSender() == nullptr || sender == nullptr)) { if (0 == observer->getHandler()) { observer->performSelector(sender); } } } }最后,该观察者模式采用的是推模型,即由目标对象去通知所有的观察者。其实CCNotificationCenter和CCNotificationObserver更准确的叫法是:订阅发布模式。
这里要说明的是:
1、postNotification可以传递一个CCObject类型的参数,这个参数可以可以是CCInteger、CCString类型,通过这个可以传递参数给观察者的回调函数。
2、注册观察者之后,即addObserver,要记得removeObserver,否则可能引起内存泄露,因为addObserver会把观察者的应用计数+1;
本文参考点击打开链接