zoukankan      html  css  js  c++  java
  • 模拟EventCenter,flash自带的事件机制的一个解耦框架,callback回调方式用于模块之间的通信

    之前写了一个简化版的puremvc,mvc框架,

    后来参考一个ARPG项目的架构,目前用于解耦的我所了解的两种方式都罗列下:

    1.EventCenter模式:

    package com.cw.war.module.guide
    {
        
        import flash.events.EventDispatcher;
    
        /**
         * 用来解耦新手指引和各个模块
         * @author elvisjiang
         * @data 2012-9-25
         */    
        public class GuideEventCenter
        {
            private static var instance:GuideEventCenter;
            public static function getInstance () : GuideEventCenter
            {
                if (instance == null)
                {
                    instance = new GuideEventCenter ();
                }
                return instance;
            }
            public static function get I():GuideEventCenter
            {
                if (instance == null)
                {
                    instance = new GuideEventCenter ();
                }
                return instance;
            }
            public function GuideEventCenter()
            {
                ed = new EventDispatcher();
                if(instance != null) throw new Error ( "Singleton Error" );
            }
            
            private var ed:EventDispatcher;
            private var  _listener:Array;
            
            
            public function dispatchEvent(type:String,data:Object = null):void
            {
                ed.dispatchEvent(new GuideEvent(type,data));
            }
            public function addEventListener(type:String,fun:Function):void
            {
                if(!_listener)
                {
                    _listener = [];
                }
                
                _listener.push({type:type,listener:fun});
                ed.addEventListener(type,fun);
            }
            public function removeEventListener(type:String,fun:Function):void
            {
                ed.removeEventListener(type,fun);
            }
            
            public function destroy():void
            {
                //移除监听
                while(_listener.length > 0)
                {
                    var item:Object = _listener.shift();
                    removeEventListener(item.type,item.listener);
                }
                _listener.length = 0;
                _listener = null;
                ed = null;
                instance = null;
            }
        }
    }

    上述的核心就是一个eventDispatcher用于转发,

    比方说模块1 : proxy里面可以 这样写:

    EventCenter.addEventListener("背包数据回包",_fun1);

    服务器背包数据回包之后可以 EventCenter.dispatchEvent();

    这有个缺点,整个游戏会监听很多事件,上个项目至少监听了500个,这个ed太任重道远了,

    2.下面讲另一种解耦方式,函数回调的方式:

    package 
    {
        import flash.utils.Dictionary;
        
        import net.libra.core.Notification;
        import net.libra.core.interfaces.IController;
        import net.libra.core.interfaces.INotifier;
        import net.libra.log.Log;
        import net.libra.utils.HashMap;
        import net.libra.utils.StringUtils;
    
        /**
         * 事件转发器
         * @author elvisjiang
         * @data 2012-6-11
         */
        public class CallPool
        {
            private static var _instance:CallPool;
            
            public static function getInstance () : CallPool
            {
                if (_instance == null)
                {
                    _instance = new CallPool (new PrivateClass());
                }
                return _instance;
            }
            public static function get I():CallPool
            {
                if (_instance == null)
                {
                    _instance = new CallPool (new PrivateClass());
                }
                return _instance;
            }
            public static function get instance():CallPool
            {
                if (_instance == null)
                {
                    _instance = new CallPool (new PrivateClass());
                }
                return _instance;
            }
            
            //---------------------------------------------------------------->
            private var _callbacks:Dictionary;
            
            public function CallPool(prv :PrivateClass)
            {
                _callbacks = new Dictionary(true);
            }
            //---------------------------------------------------------------------->
            /**
             * 注册消息回调 
             * 相当于addEventlistner;
             * @param noticationName 消息Type
             * @param fun 回调函数
             */        
            public function addCallBack(notificationName:String,callback:Function):void
            {
                if(_callbacks[notificationName] == null){
                    _callbacks[notificationName] = [];
                }
                var index:int = findAt(notificationName,callback);
                if(index == -1){
                    _callbacks[notificationName].push(callback);
                }
            }
            /**
             * 销毁消息回调 
             * @param notificationName
             * @param callback
             * 
             */        
            public function removeCallBack(notificationName:String,callback:Function):void
            {
                var index:int = findAt(notificationName,callback);
                if(index != -1){
                    (_callbacks[notificationName] as Array).splice(index,1);
                }
            }
            private function findAt(notificationName:String,callback:Function):int
            {
                var calls:Array = _callbacks[notificationName];
                if(calls == null)
                    return -1;
                var index:int = 0;
                for each(var call:Function in calls){
                    if(call == callback)
                        return index;
                    index++;
                }
                return -1;
            }
    
            /**
             * 向所有的注册的函数发消息
             */
            public function sendNotification(notificationName:String,body:Object = null):void
            {
                if(_callbacks[notificationName] != null)
                {
                    var calls:Array = _callbacks[notificationName];
                    if(calls == null || calls.length <= 0)
                        return ;
                    var index:int = 0;
                    for each(var call:Function in calls){
                        call.apply(null,[new Notification(notificationName,body)]);
                        index++;
                    }
                }
            }
    
        }
    }
    class PrivateClass{}

    模块1入口
    package { import net.libra.core.Notification;
    /** * * @author elvisjiang * @data 2012-11-14 */ public class Module1 { public function Module1() { CallPool.I.addCallBack("123",_callback1); CallPool.I.addCallBack("456",_callback1); CallPool.I.removeCallBack("123",_callback1); } private function _callback1(notification:Notification):void { switch(notification.getName()) { case "123": trace("Module1收到123"); break; case "456": trace("Module1收到456"); break; } } } }
    模块2入口
    package { import net.libra.core.Notification; /** * * @author elvisjiang * @data 2012-11-14 */ public class Module2 { public function Module2() { CallPool.I.addCallBack("123",_callback1); } private function _callback1(notification:Notification):void { trace("Module2--123接收到",notification.getBody().name); } } }

     测试类:

    package
    {
    	import flash.display.Sprite;
    	
    	import net.libra.core.Notification;
    
    	/**
    	 * 
    	 * @author elvisjiang
    	 * @data 2012-11-14
    	 */	
    	public class TestCallPool extends Sprite
    	{
    		public function TestCallPool()
    		{
    			new Module1();
    			//new Module2();
    			CallPool.I.sendNotification("123",{name:"xxx123"});
    			CallPool.I.sendNotification("456",{name:"xxx456"});
    		}
    	}
    }
    

     消息体类

    package net.libra.core
    {
        import flash.events.Event;
    
        /**
         * 事件通知
         * @author elvisjiang
         */
        public class Notification
        {
            private var name:String;
            private var body : Object;
            private var type : String;
    
            /**
             * 创建一个通知对象
             * @param name    事件名称
             * @param body    事件携带的数据参数
             * @param type    事件类型
             */
            public function Notification(name : String, body : Object = null,type : String = "")
            {
                this.name = name;
                this.body = body;
                this.type = type;
            }
    
            /**
             * @inheritDoc
             */
            public function getName() : String
            {
                return this.name;
            }
    
            /**
             * @inheritDoc
             */
            public function setBody(body : Object) : void
            {
                this.body = body;
            }
    
            /**
             * @inheritDoc
             */
            public function getBody() : Object
            {
                return this.body;
            }
    
            /**
             * @inheritDoc
             */
            public function setType(type : String) : void
            {
                this.type = type;
            }
    
            /**
             * @inheritDoc
             */
            public function getType() : String
            {
                return this.type;
            }
        }
    }

    这种方式是基于函数回调的,就是一个字符串对应一个函数列表,当callPool.sendNotication的时候,函数列表会挨个执行。

    两种方式各有优缺点,有的人说eventdispatcher是最高效率的,但是用内存换效率了,函数回调的方式弱化了a lot of 监听,但如果是高性能要求的可以用eventCenter的方式,有人说监听500到1000个函数根本不在话下,看个人了,如果你觉的太重了,就用下面那个,呵呵。

  • 相关阅读:
    多个tab切换demo
    react添加和删除定时器的地方
    编写C语言的两种方法----Visual Studio/CodeBlocks
    C++学习笔记---引用的本质
    C++学习笔记---指针
    C++学习笔记---数据类型
    博客园皮肤SimpleMemory深色风格皮肤
    SQL DELETE语句如何让表使用别名的方法
    Asp.Net实现局部刷新,ScriptManager和UpdatePanel控件的使用
    由于可能不会将凭据发送到远程计算机,因此将不会进行连接。若要获得协助,请与您的系统管理员联系。(转)
  • 原文地址:https://www.cnblogs.com/as3lib/p/2772822.html
Copyright © 2011-2022 走看看