Flash/Flex/AIR:ActionScript 2定时器--基于观察者模式的实现

这是一个基于观察者模式而设计的ActionScript2定时器的完整源码

/**

* (#)The Timer class used for fixed cycle operationg

* @author <a href="mailto:yoshua.estelle@gmail.com">WarGrey</a>

* @version 2.0

* @since ActionScript 2.0

* @see mx.events.EventDispatcher

*/

import mx.events.EventDispatcher;


class wargrey.util.Timer extends EventDispatcher{

public static var INITIATE:String="initiate";

public static var TIMECYCLE:String="timecycle";

public static var TERMINATE:String="terminate";

//This timer ID

private var id:Number;

//The repetition times that has happened after begin executing

private var repetition:Number;

//The interval of each repetition

private var _interval:Number;

public function get interval():Number{

return _interval;

}

//This variable is used to show whether the timer has launched.

private var isLaunched:Boolean;

public function Timer(interval:Number){

//Set the _interval with the default value is 1000 ms.

_interval=(interval>0)?interval:1000;

//The repetition times is cleared to 0

repetition=0;

//The isLaunched is setted by false

isLaunched=false;

}

//Begin to timing and dispatch the "initiate" event.

public function start():Void{

var event:Object=new Object();

event.type="initiate";

event.target=this;

event.interval=interval;

dispatchEvent(event);

isLaunched=true;

id=setInterval(this,"run",interval);

}

//Stop the time and dispatch the "terminate" event.

public function stop():Void{

clearInterval(id);

isLaunched=false;

var event:Object=new Object();

event.type="terminate";

event.target=this;

event.times=repetition;

repetition=0;

dispatchEvent(event);

}

//Registe the observers only before this timer launched, or it will call the method named "addEventListenerFailed" of observer and return false;

public function addEventListener(event:String,handler:Object):Boolean{

if (!isLaunched){

super.addEventListener(event,handler);

return true;

}else{

if (handler["addEventListenerFailed"]!=undefined){

var failure:Object=new Object();

failure.type=event;

failure.target=this;

failure.times=repetition;

handler.addEventListenerFailed(failure);

}

return false;

}

}

//Execute the repetition method which dispatches the "timecyle" event.

private function run():Void{

repetition++;

var event:Object=new Object();

event.type="timecycle";

event.target=this;

event.times=repetition;

dispatchEvent(event);

}

public function toString():String{

if (id==undefined){

var msg="unlaunched";

}else{

var msg="Timer["+id.toString()+"]";

}

return msg;

}

}

该定时器类Timer继承于mx.events.EventDispatcher,这样一来便成了一个功能完善的广播源,代码书写上也比混入更清晰易懂。既然是基于观察者模式的定时器,现在又有了广播源,那当然也需要一个观察者通过timer.addEventListenertimer.removeEventListener等方法来注册取消感兴趣的事件。对于一般的面向对象语言,对于观察者和广播源必须专门定制,或通过其他机制来实现,因此或多或少会造成了性能损失,不过ActionScript2也是一个相当不错的动态语言,处理类似的问题具有先天的优势,因此任何一个Object都可以充当任何广播源的观察者,自然对于定时器类来说,其提供的三个事件,即initiatetimecycleterminate,因此它的观察者应至少提供其中的一个方法才能正确注册。当然不提供也行,那样Timer就当注册没发生。下面详细介绍观察者的可选方法:

initiate事件:对应于Timer.INITIATE静态成员,是启动定时器时广播的事件。

timercycle事件:对应于Timer.TIMERCYCLE静态成员,是每次定时重新执行时广播的事件。

terminate事件:对应于Timer.TERMINATE静态成员,是停止定时器时广播的事件。

addEventListenerFailed事件:当注册事件失败时广播此事件。为了避免混乱,该定时器规定只有当定时器未启动时才能注册事件,所以如果注册事件时定时器已经启动便会导致注册事件失败。

对于所有事件,都有一个Object类型的参数,该参数包含如下属性:

  • type:事件名称。

  • target:广播源对象实例。

  • interval:仅限于initiate事件,该定时器实例定时时间间隔。

  • timesinitiate事件不适用,到目前为止定时器重复执行的次数。

下面是个测试用例,为方便测试做成了Flash SWC组件。

//The First Observer

class wargreytest.util.timer.TimerTestObject {

private var name;

public function TimerTestObject(name:String){

this.name=(name.length>0)?name:"default";

}

private function initiate(event:Object):Void{

_root.display(name+" has launched.");

_root.newLine();

}

private function timecycle(event:Object):Void{

_root.display(name+" recycled for "+event.times.toString()+" times.");

_root.newLine();

}

private function terminate(event:Object):Void{

_root.display(name+" has terminated.");

_root.newLine();

}

}


//The Second Observer

import wargreytest.util.timer.*;

class wargreytest.util.timer.TimerTestObject2 extends TimerTestObject{

public function TimerTestObject2(name:String){

super(name);

}

private function addEventListenerFailed(event:Object):Void{

_root.display(name+" registe '"+event.type+"' listener failed.");

_root.newLine();

}

}


//The Timer TestCase Component

import wargreytest.util.timer.*;

import wargrey.util.*;

import wargrey.extension.GraphicalInterface;

[InspectableList("interval","instanceno","seconds")]

class wargreytest.util.TimerTest extends MovieClip{

private var id:Number;

private var timer:Timer;

private var _interval:Number;

[Inspectable(name="interval",defaultValue="1000",verbose=0)]

public function set interval(itl:Number):Void{

_interval=(itl>0)?itl:1000;

}

public function get interval():Number{

return _interval;

}

private var _instanceno:Number;

[Inspectable(name="instanceno",defaultValue="3",verbose=0)]

public function set instanceno(isn:Number):Void{

_instanceno=(isn>0)?isn:3;

}

public function get instanceno():Number{

return _instanceno;

}

private var _seconds:Number;

[Inspectable(name="seconds",defaultValue="5",verbose=0)]

public function set seconds(s:Number):Void{

_seconds=(s>0)?s:5;

}

public function get seconds():Number{

return _seconds;

}

private function onLoad():Void{

this._visible=false;

var gi:GraphicalInterface=new GraphicalInterface();

gi.extend(_root);

timer=new Timer(interval);

for (var i=instanceno-1;i>=0;i--){

var temp:TimerTestObject=new TimerTestObject("timeListener"+i.toString());

timer.addEventListener("initiate",temp);

timer.addEventListener("timecycle",temp);

timer.addEventListener("terminate",temp);

}

timer.start();

id=setInterval(this,"stopTest",seconds*1000);

var temp:TimerTestObject=new TimerTestObject("timeListener"+instanceno.toString());

timer.addEventListener("initiate",temp);

var temp:TimerTestObject=new TimerTestObject2("timeListener"+(instanceno+1).toString());

timer.addEventListener("timercycle",temp);

}

private function stopTest():Void{

timer.stop();

clearInterval(id);

}

}

补充说明:定时器的定时时间间隔只能在构造Timer实例时指明,以后便不能更改,若构造时省略则默认为1000,单位毫秒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值