模拟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个函数根本不在话下,看个人了,如果你觉的太重了,就用下面那个,呵呵。

posted on 2012-11-16 10:53  防空洞123  阅读(395)  评论(0编辑  收藏  举报

导航