設計模式之觀察者2
阿新 • • 發佈:2019-02-08
COCOS2D-X中的觀察者
在cocos2d-x中被觀察者是NotificationCenter,但它不是通過自身狀態改變來通知觀察者,而是通過顯示地傳送觀察者感興趣的訊息(postNotification)來通知它們。每一種訊息型別可以對應多個觀察者,同時,每一個觀察者也可以“觀察”多個訊息型別。其次,觀察者定義相應的響應事件同訊息型別關聯,當某個地方觸發postNotification來廣播一個訊息的時候,NotificationCenter會遍歷所有的觀察者,判斷它們註冊的訊息型別是否匹配,如果匹配,則觸發相應的註冊響應事件。最後,該觀察者模式採用的是推模型,即由目標物件去通知所有的觀察者。 其實NotificationCenter和NotificationObserver更準確的叫法是:訂閱釋出模式。
觀後感
CCNotificationObserver相當於一個組裝器,把object(物件)、func(物件的方法)、name(事件)組裝到一起,變成一個Observer實體。 CCNotificationCenter中封裝了一個CCArray容器,同一個物件、不同事件可以當做不同的Observer新增,總之,是以event來區別不同的觀察者而不是object。
例項
//新增觀察者 CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(HelloWorld::myNotification), "MY_NOTIFICATION", NULL); /** 一般的在接受通知的一方在接受完通知後需要remove監聽。 (注意第二個方法: returns the number of observers removed)*/ void removeObserver(CCObject *target,const char *name); int removeAllObservers(CCObject *target); //事件名字 CCNotificationCenter::sharedNotificationCenter()->postNotification("MNOTIFICATION", (CCObject*)1);
CCNotificationCenter.h
/** * @js NA:不適用 * @lua NA:不適用 */ //觀察者 class CC_DLL CCNotificationObserver : public CCObject { public: /** @brief 構造一個觀察者 * @param target 想做觀察者的物件 * @param selector 回撥方法 * @param name 訊息名字 * @param obj 將被傳遞給回撥函式的額外引數 */ CCNotificationObserver(CCObject *target, SEL_CallFuncO selector, const char *name, CCObject *obj); /** 釋放成員 */ ~CCNotificationObserver(); /** target通過回撥方法呼叫obj */ void performSelector(CCObject *obj); private: /** 定義CCObject型別的物件m_target,並建立一個getTarget方法 */ CC_PROPERTY_READONLY(CCObject *, m_target, Target); CC_PROPERTY_READONLY(SEL_CallFuncO, m_selector, Selector); CC_PROPERTY_READONLY(char *, m_name, Name); CC_PROPERTY_READONLY(CCObject *, m_object, Object); //建立get和set方法 CC_PROPERTY(int, m_nHandler,Handler); }; //被觀察者 class CC_DLL CCNotificationCenter : public CCObject { private: //判斷是否存在name名字的target bool observerExisted(CCObject *target,const char *name); //觀察者集合 CCArray *m_observers; //lua專用 int m_scriptHandler; public: /** 建構函式,初始化集合m_observers */ CCNotificationCenter(); /** 釋放集合m_observers */ ~CCNotificationCenter(); /** 獲取單例物件 */ static CCNotificationCenter *sharedNotificationCenter(void); /** 銷燬單例物件 */ static void purgeNotificationCenter(void); /** 新增觀察者 * @param target 觀察者 * @param selector 觀察者的回撥方法 * @param name 通知訊息 * @param 傳給回撥方法的額外引數 */ void addObserver(CCObject *target, SEL_CallFuncO selector, const char *name, CCObject *obj); /** @brief 移除指定name的target * @param target The target of this notification. * @param name The name of this notification. */ void removeObserver(CCObject *target,const char *name); /** @brief 移除這個target的所有觀察者 * @param target. * @returns 返回被移除觀察者的數量 */ int removeAllObservers(CCObject *target); /** lua指令碼中使用的註冊、登出觀察者*/ void registerScriptObserver(CCObject *target,int handler,const char* name); void unregisterScriptObserver(CCObject *target,const char* name); /** 執行指定name的觀察者的回撥方法 */ void postNotification(const char *name); void postNotification(const char *name, CCObject *object); /** 獲取指令碼的回撥方法 */ inline int getScriptHandler() { return m_scriptHandler; }; int getObserverHandlerByName(const char* name); };