2010年2月23日 星期二

AdvancedProxy

這個物件是動態的,可以完全代理另一個物件。
主要功能如下:
1.代理另一個物件的所有屬性(無法區分唯讀、唯寫)和方法。
2.若被代理物件發出這個Proxy有偵聽的事件,一律使用Event.clone轉發。
3.使用$alias產生屬性及方法的別名。
注意事項:
1.for...in迴圈,只會跑這個Proxy上的屬性及方法(含別名),不會有被代理者的。
2.若被代理者的屬性、方法名和Proxy擁有的同名,Proxy的屬性及方法優先。
3.動態加入的屬性方法,不會加到被代理者身上。
4.$super(被代理者)的更換,不會影響Proxy現有的屬性、方法。已加到Proxy上的事件偵聽式也不會消失。



AdvancedProxy
package tw.right929.proxy
{
    import flash.events.*;
    import flash.utils.*;
    
    import tw.right929.event.AdvancedEventDispatcher;
    
    use namespace flash_proxy
    
    /**
     * 這個物件是動態的,可以完全代理另一個物件。
     * 主要功能如下:
     * 1.代理另一個物件的所有屬性(無法區分唯讀、唯寫)和方法。
     * 2.若被代理物件發出這個Proxy有偵聽的事件,一律使用Event.clone轉發。
     * 3.使用$alias產生屬性及方法的別名。
     * 注意事項:
     * 1.for...in迴圈,只會跑這個Proxy上的屬性及方法(含別名),不會有被代理者的。
     * 2.若被代理者的屬性、方法名和Proxy擁有的同名,Proxy的屬性及方法優先。
     * 3.動態加入的屬性方法,不會加到被代理者身上。
     * 4.$super(被代理者)的更換,不會影響Proxy現有的屬性、方法。已加到Proxy上的事件偵聽式也不會消失。
     */
    public dynamic class AdvancedProxy extends Proxy implements IEventDispatcher
    {
        private var _propertyMap:Object        =    new Object();
        private var _aliasMap:Object    =    new Object();
        private var _$super:*;
        private var _properties:Array    =    new Array();
        private var _needUpdateProperties:Boolean    =    false;
        private var _eventDispatcher:AdvancedEventDispatcher;
        
        public function AdvancedProxy()
        {
            super();
            _eventDispatcher    =    new AdvancedEventDispatcher(this);
        }
        
        /**
         * 設定被代理的物件,會連事件也一併代理(僅轉發)。
         */
        public function get $super():*
        {
            return _$super;
        }
        public function set $super(v:*):void
        {
            if(_$super == v)
                return;
            _$super    =    v;
            _eventDispatcher.eventSource    =    _$super;
        }
        
        /**
         * 幫屬性及方法增加別名。
         * 原先的方法名不會消失,別名僅是轉發。
         * 若別名已存在,會蓋掉舊的別名。
         * 別名會出現在for...in的迴圈之中。
         * 刪除別名一樣使用delete的方法。
         */
        public function $alias(name:String , alias:String):void
        {
            _aliasMap[alias]    =    name;
        }
        
        /**
         * 傳入一個名字判斷是不是別名。
         */
        public function $isAlias(name:*):Boolean
        {
            if(name is QName)
                name    =    name.localName;
            
            if(_aliasMap[name])
                return true;
            return false;
        }
        
        private function getRealName(name:*):*
        {
            if(name is QName)
                name    =    name.localName;
            
            if(_aliasMap.hasOwnProperty(name))
                return _aliasMap[name];
            
            return name;
        }
        
        override flash_proxy function setProperty(name:*, value:*):void
        {
            name    =    getRealName(name);
            
            if(this[name] == value)
                return;
            
            _needUpdateProperties    =    true;
            
            if(_hasProperty(name))
                _propertyMap[name]    =    value;
            else if(_$super && _$super.hasOwnProperty(name))
                _$super[name] = value;
            else
                _propertyMap[name]    =    value;
        }
        
        override flash_proxy function deleteProperty(name:*):Boolean
        {
            _needUpdateProperties    =    true;
            
            if($isAlias(name))
                return delete _aliasMap[name];
            
            return delete _propertyMap[name]; 
        }
        
        override flash_proxy function callProperty(name:*, ... rest):*
        {
            name    =    getRealName(name);
            
            if(_hasProperty(name))
                return _propertyMap[name].apply(this , rest);
            else if(_$super)
                return _$super[name].apply(this , rest);
        }
        
        override flash_proxy function getProperty(name:*):*
        {
            name    =    getRealName(name);
            
            if(_hasProperty(name))
                return _propertyMap[name];
            else if(_$super)
                return _$super[name];
        }
        
        override flash_proxy function nextName(index:int):String
        {
            updateProperties();
            return _properties[index-1].toString();
        }
        
        override flash_proxy function nextNameIndex(index:int):int
        {
            updateProperties()
            if (index < _properties.length)
                return index + 1;
            else
                return 0;
        }
        
        override flash_proxy function nextValue(index:int):*
        {
            updateProperties();
            if($isAlias(_properties[index-1]))
                return _aliasMap[_properties[index-1]];
            else
                return _propertyMap[_properties[index-1]];
        }
        
        override flash_proxy function hasProperty(name:*):Boolean
        {
            if(_hasProperty(name))
                return true;
            else if(_$super && _$super.hasOwnProperty(name))
                return true;
            else
                return false;
        }
        /**
         * 尋找是否有這個屬性,含別名。
         */
        private function _hasProperty(name:*):Boolean
        {
            if(name is QName)
                name    =    name.localName;
            if(name in _propertyMap)
                return true;
            if(name in _aliasMap)
                return true;
            return false;
        }
        /**
         * 重整自已的屬性清單,含別名。
         */
        private function updateProperties():void
        {
            if(_needUpdateProperties)
            {
                _properties    =    new Array();
                for (var p:String in _propertyMap)
                    _properties.push(p);
                for (var a:String in _aliasMap)
                    _properties.push(a);
                _needUpdateProperties    =    false;
            }
        }
        
        
        public final function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
        {
            _eventDispatcher.addEventListener(type , listener , useCapture , priority , useWeakReference);
        }
        
        public final function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
        {
            _eventDispatcher.addEventListener(type , listener , useCapture);
        }
        
        public final function dispatchEvent(event:Event):Boolean
        {
            return _eventDispatcher.dispatchEvent(event);
        }
        
        public final function hasEventListener(type:String):Boolean
        {
            return _eventDispatcher.hasEventListener(type);
        }
        
        public final function willTrigger(type:String):Boolean
        {
            return _eventDispatcher.willTrigger(type);
        }
        
        public final function getAllEventListenerType():Array
        {
            return _eventDispatcher.getAllEventListenerType();
        }
        
        public final function removeAllEventListener():void
        {
            _eventDispatcher.removeAllEventListener();
        }
        
        public final function removeEventListenerByType(type:String):Array
        {
            return _eventDispatcher.removeEventListenerByType(type);
        }
        
        public final function addEventListenerByArray(listeners:Array):void
        {
            _eventDispatcher.addEventListenerByArray(listeners);
        }
        
    }
}
測試
<?xml version="1.0" encoding="utf-8"?>
<s:Application creationComplete="init()" xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768">
    <fx:Script>
        <![CDATA[
            import tw.right929.proxy.AdvancedProxy;
            
            private function init():void
            {
                var arr:Array    =    [0 , 1];
                var arrProxy:AdvancedProxy    =    new AdvancedProxy();
                arrProxy.$super    =    arr;
                arrProxy.push(2,3);
                trace(arr);//0,1,2,3
                arrProxy.$alias("push" , "addChild");
                arrProxy.addChild(4,5);
                trace(arr);//0,1,2,3,4,5
                delete arrProxy["addChild"];
                
                var s:Sprite    =    new Sprite();
                arrProxy.$super    =    s;
                arrProxy.addEventListener("E" , onE);
                s.dispatchEvent(new Event("E"));//onE
            }
            
            private function onE(e:Event):void
            {
                trace("onE");
            }
        ]]>
    </fx:Script>
</s:Application>


這個類別是從AdvancedObject中抽出來的,AdvancedObject也需要改寫。

沒有留言:

張貼留言

追蹤者