zoukankan      html  css  js  c++  java
  • cocos creator主程入门教程(六)—— 消息分发

    五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑。本系列文章以TypeScript为介绍语言。

    本篇开始介绍游戏业务架构相关的内容。在游戏业务层,所有需要隔离的系统和模块间通信都可以通过消息分发解耦。例如网络返回通知、数据更新同步到界面等。

    消息分发基于观察者模式设计。需要处理消息的地方向消息中心注册监听回调,派发消息时,调用消息中心的派发接口遍历该消息的监听队列,调用对应的回调方法。

    先定义监听回调类型

    /**
     * 消息监听回调方法
     */
    export type NotifyListener = (src: any, data: any) => void;
    

      

    通过key-value方式保存监听队列

    private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();
    

      

    接口定义

        /**
         * 添加多次监听者,需要手动移除
         * @param msg 
         * @param listener 
         * @param target 
         */
        public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
    
        /**
         * 添加单次监听者,事件触发后即移除
         * @param msg 
         * @param listener 
         * @param target 
         */
        public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
    
        /**
         * 移除指定消息指定的监听者
         * @param msg 
         * @param listener 
         */
        public static removeMsgListener(msg: string, listener: NotifyListener): void {}
    
        /**
         * 移除指定消息所有监听者
         * @param msg 
         */
        public static removeMsgAllListeners(msg: string): void {}
    
        /**
         * 移除指定目标对指定消息的监听
         * @param msg 
         * @param target 
         */
        public static removeTargetMsgListen(msg: string, target: any): void {}
    
        /**
         * 移除指定目标所有消息监听
         * @param target 
         */
        public static removeTargetAllMsgListen(target: any): void {}
    
        /**
         * 派发消息
         * @param msg 
         * @param src 
         * @param data 
         */
        public static notify(msg: string, src: any, data: any): void {}
    

      

    在添加移除实现中,需要注意某消息可能正在派发。

    对于一个消息新添加的监听者,应该在当前队列消息派发完后再派发,因此,添加一个待添加队列

    private static listener2add: Array<NotifyListenerInfo> = [];
    

      

    在添加监听者时做以下判断

        // 该消息正在派发,放入待添加队列
            if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
                NotifyCenter.listener2add.push(info);
                return;
            }
    

      

    同样在移除监听者时,可能正在派发消息,避免对队列的修改导致for循环异常,添加一个待移除队列,派发消息时,如果该监听者在移除队列则不派发。在消息派发完后再将其移出队列

    private static listener2remove: Array<NotifyListenerInfo> = [];
    

      

    在移除监听者时做以下判断

            // 该消息正在派发,放入待移除队列
                    if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
                        NotifyCenter.listener2remove.push(list[i]);
                    } else {
                        list.splice(i, 1);
                    }
    

      

    派发消息时遍历指定消息下的队列

            // 队列不存在,不需要处理
            let list = NotifyCenter.msg2listDict.get(msg);
            if (!list) {
                return;
            }
    
            // 标记消息正在派发,多个消息可能同时在派发,同一消息可能标记多次
            NotifyCenter.notifyMsgs.push(msg);
    
            // 处理消息派发
            for (let i = 0, n = list.length; i < n; i++) {
                NotifyCenter._dispatch(list[i], src, data, false);
            }
    

      

    派发消息时先判断是否在移除队列

    // 在移除队列,不派发
            if (NotifyCenter.listener2remove.indexOf(info) >= 0) {
                return;
            }
    

      

    当前队列派发完后检查待添加队列

    // 处理待添加队列派发
            for (let i = 0, n = msg2add.length; i < n; i++) {
                if (listener2add[i].msg == msg) {
                    NotifyCenter._dispatch(listener2add[i], src, data, true);
                }
            }
    

      

    引入消息分发中心,隔离的系统、模块间通过消息监听和派发通信,避免互相引用耦合。

    消息分发先说到这里,下一篇我们将介绍游戏业务层架构。

  • 相关阅读:
    Host IP地址 is not allowed to connect to this MySQL server
    本地或远程连接mysql:Unable to connect to any of the specified MySQL hosts.
    Table xxx is marked as crashed and should be repaired
    使用Linq 做数据去重
    SharePoint2010与Reporting Services集成方案
    上下左右布局(DIV+CSS)
    .NET 内存管理—CLR的工作
    删除数据库所有用户表
    未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序
    c# 10位数int时间单位换算为datetime
  • 原文地址:https://www.cnblogs.com/niudanshui/p/10421757.html
Copyright © 2011-2022 走看看