ActionScript2 delegate 研究(下)

博客对比了Delegate和EventDispatcher的优缺点,综合两者构思了多播委托模型。介绍了事件代理句柄EventHandler、事件参数类EventArgs及其子类MouseEventArgs,还给出了多播接口和主要Event类的实现,最后用测试组件进行测试并展示了测试结果。

在上两篇中,我们研究了Macromedia Updater 2的Delegate的用法、起源、实现、优点。
然而这个Delegate可以很好的实现一个事件对应一个代理方法。但很多时候不是这样的,有更多的事物需要知道发生了这件事,然后调用自己的处理函数。比如我的一个组件,鼠标按下去的时候,有可能一个Label组件知道这个事件后改变自己的标题changeText(),同时也有可能一个MediaPlayback组件知道这个事件后要播放一个FLV视频play()……  而用Delegate,只能用一个函数来代理这些事务。然而这些事务是不同对象的方法,changeText()方法是属于Label对象的,play()方法是属于MediaPlayback对象的。当然可以把这些放在一个方法内,如下:
function EevntHandler()
{
    lbl.changeText();
    mpb.play();
}
但很多时候这些方法不能写在一个EventHandler函数中,这时我们想到了EventDispatcher,他可以让一个对象增加监听器,然后由这个对象广播事件给各个监听者。这些监听者监听到这些事件后,各自调用自己的处理事件。但Macromedia的EventDispatcher最大的一个缺点就是很多事件发生的相关信息没有传递,如鼠标点下去,很多时候需要鼠标的位置,按下的键是哪个。EventDispatcher却没有一个很好的规范去传递。

综合两者的优点。我大致构思了多播委托的模型。

Delegate改成EventHandler,构造函数稍为变化一下:

//****************************************************************************
// @FileName EventHander.as
// @Package com.flashvan.event
// @Description 事件代理句柄
// @Author aol
// @Email jeremy1982@21cn.com
// @Create 2004.10.21
// @LastChange 2004.10.21
// @History
//****************************************************************************

import com.flashvan.event.EventArgs;
import com.flashvan.event.except.Exception;

class com.flashvan.event.EventHandler extends Object
{
 /**
 Creates a functions wrapper for the original function so that it runs
 in the provided context.
 @parameter obj Context in which to run the function.
 @paramater func Function to run.
 */
 static function create(obj:Object, func:Function):Function
 {
  var f = function()
  {
   var target = arguments.callee.target;
   var func = arguments.callee.func;
   
//    
//    if(typeof(arguments[0])!= "object" && (arguments[1] instanceof EventArgs))
//     throw new Exception("参数得满足[sender:Object,e:EventArgs]的形式",this,[target,func]);

   return func.apply(target, arguments);
  };
  
  f.target = obj;
  f.func = func;

  return f;
 }

 function EventHandler(o:Object,f:Function)
 {
  obj = o
  func = f;
 }

 private var func:Function;
 private var obj:Object;

 function createEventHandler():Function
 {
  return create(obj, func);
 }
}

一个专门记录事件发生相关信息EventArgs:

//****************************************************************************
// @FileName EventArgs.as
// @Package com.flashvan.event
// @Description 事件参数类(事件发生之后传递的就是这个)
// @Author aol
// @Email jeremy1982@21cn.com
// @Create 2004.10.21
// @LastChange 2004.10.21
// @History
//****************************************************************************

class com.flashvan.event.EventArgs
{
 function EventArgs()
 {
 
 };
 
 public static function get Empty():EventArgs
 {
  return new EventArgs();
 }
 
 public function Dispose():Void
 {
  delete this;
 }
};

由EventArg继承下来的,例如专门针对鼠标事件的MouseEvntArgs
import com.flashvan.event.EventArgs;

class com.flashvan.component.core.MouseEventArgs extends EventArgs
{
 private var _clicks:Number;//鼠标被按下的次数
 
 //按下鼠标的哪个按钮
 // 0为没按, 1为左键, 2为右键, 3为滚轮
 // 要全部监测到那得用未公开函数了 ^_^
 private var _button:Number;
 
 private var _x,_y:Number;//鼠标位置
 
 private var _delta:Number;//滚轮位置
 
 private var _springTime:Number;//触发时间
 
 public function MouseEventArgs(button:Number,clicks:Number,x:Number,y:Number,delta:Number)
 {
  _springTime = getTimer();
  _button = button;
  _clicks = clicks;
  _x  = x;
  _y  = y;
  _delta  = (delta == null)? 0:delta;
  
 }
 
 public function get X():Number
 {
  return _x;
 }
 
 public function get Y():Number
 {
  return _y;
 }
 
 public function get Clicks():Number
 {
  return _clicks;
 }
 
 public function get Button():Number
 {
  return _clicks;
 }
 
 public function get Delta():Number
 {
  return _delta;
 }
 
 //触发时间
 public function get SpringTime():Number
 {
  return _springTime;
 }
}

要实现多播至少要实现这列的多播接口:
import com.flashvan.event.EventArgs;
import com.flashvan.collections.ArrayList;
import com.flashvan.event.EventHandler;

interface com.flashvan.event.IMulticastEventDelegate
{
//  public function AddEventHandler(o:Object,f:Function):Void;
 public function AddEventHandler(eh:EventHandler):Void;
 
 public function getInvocationList():ArrayList;
 
//  public function RemoveEventHandler(o:Object,f:Function):Void;
 public function RemoveEventHandler(eh:EventHandler):Void;
 
 public function RemoveAllEventHandler():Void;
 
 public function InvokeAllEventHandler(sender:Object,e:EventArgs):Void;

}

最主要的Event类实现了这个接口:

import com.flashvan.event.IMulticastEventDelegate;
import com.flashvan.collections.ArrayList;
import com.flashvan.collections.IEnumerator;
import com.flashvan.event.EventArgs;
import com.flashvan.event.EventHandler;


class com.flashvan.event.Event implements IMulticastEventDelegate
{
 private var invocationlist:ArrayList;
 
 public function Event()
 {
  invocationlist = new ArrayList();
 }
 
 
//  public function AddEventHandler(o:Object,f:Function):Void
//  {
//   invocationlist.Add({object:o,method:f});
//  }
//  public function RemoveEventHandler(o:Object,f:Function):Void
//  {
//   invocationlist.Remove({object:o,method:f});
//  }

 public function AddEventHandler(eh:EventHandler):Void
 {
  invocationlist.Add(eh);
 }
 public function RemoveEventHandler(eh:EventHandler):Void
 {
  invocationlist.Remove(eh);
 }
 
 public function RemoveAllEventHandler():Void
 {
  invocationlist.Clear();
 }
 
 public function getInvocationList():ArrayList
 {
  return invocationlist;
 }
 
//  public function InvokeAllEventHandler(sender:Object,e:EventArgs):Void
//  {
//   var enumerator:IEnumerator = invocationlist.GetEnumerator();
//   while(enumerator.MoveNext())
//   {
//    var obj:Object = enumerator.getCurrent().object;
//    var f:Function = enumerator.getCurrent().method;
//    f.apply(obj,[sender,e]);
//   }
//  }

 public function InvokeAllEventHandler(sender:Object,e:EventArgs):Void
 {
  var enumerator:IEnumerator = invocationlist.GetEnumerator();
  while(enumerator.MoveNext())
  {
   enumerator.getCurrent().createEventHandler()(sender,e);
  }
 }
}

下面用一个测试组件来测试一下:
import com.flashvan.event.Event;
import com.flashvan.event.EventArgs;
import com.flashvan.event.EventHandler;

import com.flashvan.component.core.Component;
import com.flashvan.component.core.MouseEventArgs;

class com.flashvan.test.EventTestComponent extends Component
{
 public var MouseMove:Event;
 public var MouseDown:Event;
 
 public function EventTestComponent()
 {
  MouseMove = new Event();
 }
 
 public function onMouseMove():Void
 {
  var e:MouseEventArgs = new MouseEventArgs(0,0,_xmouse,_ymouse);
  MouseMove.InvokeAllEventHandler(this,e);
 } 
}

上面的经常都已经封装好,包括上面的测试组件,实际上很多时候用户编码只需要这些:

新建一个fla文件,把做好的EventTestComponent拖到场景中命名为etc。

新建一个类com.flashvan.test.EventTest:

import com.flashvan.event.EventHandler;

import com.flashvan.component.core.Component;
import com.flashvan.component.core.MouseEventArgs;

import com.flashvan.test.EventTestComponent;

class com.flashvan.test.EventTest extends Component
{
 private var etc:EventTestComponent;
 public function EventDelegate(sender:Object,e:MouseEventArgs):Void
 {
  trace(sender);
 }
 
 public function EventDelegate2(sender:Object,e:MouseEventArgs):Void
 {
  trace(e.SpringTime);
 }
 
 public function EventTest(c:EventTestComponent)
 {
  etc = c;
  etc.MouseMove.AddEventHandler(new EventHandler(this,EventDelegate));
  etc.MouseMove.AddEventHandler(new EventHandler(this,EventDelegate2));
 }
 
 public static function main():Void
 {
  new EventTest(EventTestComponent(arguments[0]));
 }
 
}


fla文件主时间轴加上
com.flashvan.test.EventTest.main(etc);

Ctrl+ Enter测试,只要鼠标移动就会出现类似如下的结果:
_level0.etc
72
_level0.etc
1563

代码下载链接: https://pan.quark.cn/s/a4b39357ea24 第 一 章 概述 1-1 简述计算机程序设计语言的发展阶段。 解: 自从计算机诞生以来,程序设计语言经历了从机器语言、汇编语言到高级语言的演变过程,C++语言作为一种面向对象的编程语言,也属于高级语言范畴。 1-2 面向对象的编程语言具备哪些特性? 解: 面向对象的编程语言与传统的编程语言有着本质的区别,其设计初衷是为了更直观地模拟现实世界中存在的事物及其相互关系。这类编程语言将客观事物视为具有属性和行为的对象,通过抽象方法提取出同一类对象的共同属性(静态特征)和行为(动态特征),从而构建类。借助类的继承与多态机制,能够便捷地实现代码复用,显著缩短软件开发周期,并确保软件风格的一致性。因此,面向对象的编程语言使得程序能够较为准确地反映问题域的本质,软件开发人员可以运用人类惯用的思维模式进行开发工作。C++语言是目前应用最为广泛的面向对象编程语言。 1-3 结构化程序设计方法是什么?这种方法有哪些优势和不足? 解: 结构化程序设计的核心思想是自顶向下、逐步求精;其程序结构按照功能划分为多个基本模块;各模块之间的关联尽可能简化,在功能上保持相对独立性;每个模块内部均由顺序、选择和循环三种基本结构构成;模块化实现的具体途径是利用子程序。结构化程序设计由于采用模块分解与功能抽象,自顶向下、分而治之的策略,从而有效地将一个较为复杂的程序系统设计任务分解成许多易于管理和处理的子任务,便于开发与维护。 尽管结构化程序设计方法具备诸多优点,但它本质上仍是一种面向过程的程序设计方法,将数据与处理数据的操作分离为相互独立的实体。当数据结构发生变化时,所有相关的处理过程都需要进行相应的调整,每一种...
已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 【高清晰度壁纸】是一种适用于计算机或移动设备的高解析度图像,通常用于定制用户界面,以增强视觉感受。$4K$分辨率指的是宽度约为$3840$像素,高度约为$2160$像素的显示标准,这种分辨率提供了极为清晰的细节,使得图像在大尺寸屏幕上呈现更为生动和逼真的效果。本压缩文件内含$20$张$4K$高清晰度壁纸,每张均从知名搜索引擎必应及彼岸图网中经过细致挑选。这些壁纸的题材丰富多样,涵盖了自然景观、科幻元素、游戏场景以及人物画像等多个方面,能够满足不同用户的需求。 1. **$125c1aa02ad94869ef055b870a54af560ad1574e144e03-qL6oaN_fw658.gif$**:这可能是一张动态壁纸,由于$gif$格式支持动态效果,或许包含有趣的动画元素,为桌面增添活力。 2. **$204b05b99e9b404aa6436f3c7c03d9c9.jpeg$**:$JPEG$是一种常见的静态图像格式,适合存储高品质照片,可能是一张风景或人物图片。 3. **加拿大班夫国家公园的朱砂湖的星空$4K$壁纸_彼岸图网.jpg**:这张壁纸展现了自然的宏伟,将班夫国家公园的优美湖泊与璀璨星空相结合,为用户带来宁静且和谐的视觉体验。 4. **《星球大战堕落秩序(Star Wars Jedi_ Fallen Order)》$4K$游戏壁纸_彼岸图网.jpg**:这是一张基于热门游戏《星球大战:堕落秩序》设计的壁纸,对于游戏爱好者而言极具吸引力,可能包含游戏中的角色或场景。 5. **陈钰琪倚天屠龙记$4K$壁纸_彼岸图网.jpg**:陈钰琪...
源码下载地址: https://pan.quark.cn/s/95927341e579 该方法适用于二进制数值向十进制数值的转化,其中A代表十进制数值,B代表二进制数值。{A,B}序列会执行位移操作,每次左移一位,同时检验A中的每四位数值是否>4,若超过四则进行加三调整,否则维持原状;B的位数决定了左移操作的重复次数。最终,A的数值即为B转换后的十进制表达。此代码示例专注于32位二进制数值向十进制数值的转换。在数字操作领域,二进制与十进制之间的相互转换是一项基础性操作。二进制体系(Base-2)采用0和1两种符号来表示数值,而十进制体系(Base-10)则使用0到9这十个符号。在计算机科学范畴内,特别是在硬件描述语言(例如Verilog)的应用中,掌握并执行此类转换显得尤为关键。下文将深入阐述如何借助Verilog代码实现32位二进制数值向十进制数值的转换。 我们必须明确Verilog是一种用于数字系统逻辑设计与验证的硬件描述语言。在所提及的代码中,`module b32_o(bdata, odata)`定义了一个名为 `b32_o` 的Verilog模块,该模块接收一个32位输入 `bdata`(二进制数据)并输出一个32位结果 `odata`(十进制数据)。 转换的核心逻辑在于对二进制数值进行逐位解析并依据特定规则实施调整。文中指出,针对每四位分组,我们需评估这四位数值是否大于4(4h4)。若超过四,则执行加三操作,此调整源于二进制的1000相当于十进制的8,故需将此部分值递增至下一位,即加三。该操作会在32位二进制数值的每个四位组上反复执行,总共进行32次。 代码中的 `always @(bdata)` 区块设定了一个触发机制,当 `bdata` 发生变化...
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值