詳解CocosCreator消息分發(fā)機(jī)制
概述
本篇開始介紹游戲業(yè)務(wù)架構(gòu)相關(guān)的內(nèi)容。在游戲業(yè)務(wù)層,所有需要隔離的系統(tǒng)和模塊間通信都可以通過消息分發(fā)解耦。例如網(wǎng)絡(luò)返回通知、數(shù)據(jù)更新同步到界面等。
消息分發(fā)基于觀察者模式設(shè)計(jì)。需要處理消息的地方向消息中心注冊監(jiān)聽回調(diào),派發(fā)消息時(shí),調(diào)用消息中心的派發(fā)接口遍歷該消息的監(jiān)聽隊(duì)列,調(diào)用對應(yīng)的回調(diào)方法。
具體方案
先定義監(jiān)聽回調(diào)類型
/** * 消息監(jiān)聽回調(diào)方法 */ export type NotifyListener = (src: any, data: any) => void;
通過key-value方式保存監(jiān)聽隊(duì)列
private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();
接口定義
/** * 添加多次監(jiān)聽者,需要手動移除 * @param msg * @param listener * @param target */ public static addListener(msg: string, listener: NotifyListener, target?: any): void {} /** * 添加單次監(jiān)聽者,事件觸發(fā)后即移除 * @param msg * @param listener * @param target */ public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {} /** * 移除指定消息指定的監(jiān)聽者 * @param msg * @param listener */ public static removeMsgListener(msg: string, listener: NotifyListener): void {} /** * 移除指定消息所有監(jiān)聽者 * @param msg */ public static removeMsgAllListeners(msg: string): void {} /** * 移除指定目標(biāo)對指定消息的監(jiān)聽 * @param msg * @param target */ public static removeTargetMsgListen(msg: string, target: any): void {} /** * 移除指定目標(biāo)所有消息監(jiān)聽 * @param target */ public static removeTargetAllMsgListen(target: any): void {} /** * 派發(fā)消息 * @param msg * @param src * @param data */ public static notify(msg: string, src: any, data: any): void {}
在添加移除實(shí)現(xiàn)中,需要注意某消息可能正在派發(fā)。
對于一個(gè)消息新添加的監(jiān)聽者,應(yīng)該在當(dāng)前隊(duì)列消息派發(fā)完后再派發(fā),因此,添加一個(gè)待添加隊(duì)列
private static listener2add: Array<NotifyListenerInfo> = [];
在添加監(jiān)聽者時(shí)做以下判斷
// 該消息正在派發(fā),放入待添加隊(duì)列 if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) { NotifyCenter.listener2add.push(info); return; }
同樣在移除監(jiān)聽者時(shí),可能正在派發(fā)消息,避免對隊(duì)列的修改導(dǎo)致for循環(huán)異常,添加一個(gè)待移除隊(duì)列,派發(fā)消息時(shí),如果該監(jiān)聽者在移除隊(duì)列則不派發(fā)。在消息派發(fā)完后再將其移出隊(duì)列
private static listener2remove: Array<NotifyListenerInfo> = [];
在移除監(jiān)聽者時(shí)做以下判斷
// 該消息正在派發(fā),放入待移除隊(duì)列 if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) { NotifyCenter.listener2remove.push(list[i]); } else { list.splice(i, 1); }
派發(fā)消息時(shí)遍歷指定消息下的隊(duì)列
// 隊(duì)列不存在,不需要處理 let list = NotifyCenter.msg2listDict.get(msg); if (!list) { return; } // 標(biāo)記消息正在派發(fā),多個(gè)消息可能同時(shí)在派發(fā),同一消息可能標(biāo)記多次 NotifyCenter.notifyMsgs.push(msg); // 處理消息派發(fā) for (let i = 0, n = list.length; i < n; i++) { NotifyCenter._dispatch(list[i], src, data, false); }
派發(fā)消息時(shí)先判斷是否在移除隊(duì)列
// 在移除隊(duì)列,不派發(fā) if (NotifyCenter.listener2remove.indexOf(info) >= 0) { return; }
當(dāng)前隊(duì)列派發(fā)完后檢查待添加隊(duì)列
// 處理待添加隊(duì)列派發(fā) for (let i = 0, n = msg2add.length; i < n; i++) { if (listener2add[i].msg == msg) { NotifyCenter._dispatch(listener2add[i], src, data, true); } }
引入消息分發(fā)中心,隔離的系統(tǒng)、模塊間通過消息監(jiān)聽和派發(fā)通信,避免互相引用耦合。
以上就是詳解CocosCreator消息分發(fā)機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator消息分發(fā)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
移動端刮刮樂的實(shí)現(xiàn)方式(js+HTML5)
本篇文章主要介紹了移動端刮刮樂的實(shí)現(xiàn)方法以及實(shí)現(xiàn)代碼。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-03-03QQ強(qiáng)制聊天功能代碼(加強(qiáng)版,兼容QQ2010)
QQ強(qiáng)制聊天功能代碼,腳本之家以前也發(fā)布過,但已經(jīng)不能用了,這個(gè)是新版本,經(jīng)過測試,完全兼容新版本的qq.2010-06-06JavaScript SHA1加密算法實(shí)現(xiàn)詳細(xì)代碼
這篇文章主要為大家詳細(xì)介紹了JavaScript SHA1加密算法實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的朋友可以參考一下2016-10-10javascript 廣告移動特效的實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄猨avascript 廣告移動特效的實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06ECHO.js 純javascript輕量級延遲加載的實(shí)例代碼
下面小編就為大家?guī)硪黄狤CHO.js 純javascript輕量級延遲加載的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05