Signals框架介绍(三)原生事件

注意:本文参考An introduction to AS3 Signals写成,但不是翻译,有增删改。


原生事件

为了达到替换AS3事件机制的目的,Signals当然包含了对AS3原生事件的支持。这依赖于NativeSignal类。

下面的范例演示了如何在Stage上添加单击事件。由于一看就懂,这里就不废话解释了。

[NativeSignalSample.as]

package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import org.osflash.signals.natives.NativeSignal;

[SWF(width=500,height=300,frameRate=30,backgroundColor=0xFFFFFF)]
/**
 * 测试原生事件
 * @author zrong(zengrong.net)
 */
public class NativeSignalSample extends Sprite 
{
    public function NativeSignalSample()
    {
        _click = new NativeSignal(this.stage, MouseEvent.CLICK, MouseEvent);
        _click.add(handler_click);
        //测试只发生一次的点击事件
        //_click.addOnce(handler_click);
    }

    private var _click:NativeSignal;

    private function handler_click($evt:MouseEvent):void
    {
        trace('currentTarget:',$evt.currentTarget);
        trace('target:',$evt.target);
    }
}
}

其它资料

Signals框架介绍(一)基本用法

注意:本文参考An introduction to AS3 Signals写成,但不是翻译,有增删改。


Signals是一个基于AS3的轻量级事件框架,它被设计用来代替AS3内置的Event框架。

为什么我们要放弃Event框架,改用Signals呢?原因主要有以下几点:

  1. 使用AS3内置的Event框架,必须继承EventDispatcher或者自行实现IEventDispatcher,而Signals使用组合,可以避免继承;
  2. 使用AS3内置框架在事件中实现值的传递,必须自定义事件类才可以。而Signals可以方便的实现多个强类型值的传递;
  3. Signals不使用字符串来区分不同的事件,而是使用实例;
  4. Signals的速度更快,据说是AS3内置事件机制的4倍。

来看个简单的例子吧,这个例子中的闹钟会叫我们起床。此范例部分源码来自An introduction to AS3 Signals

基本用法

先看看闹钟类AlarmClock.as

package
{
import org.osflash.signals.Signal;

/**
* Signals闹钟范例
* @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
* @author zrong(zengrong.net)
*/

public class AlarmClock
{
    public function AlarmClock()
    {
        alarm = new Signal();
    }

    /**
     * 声明一个Signal实例用来发送Signal
     */
    public var alarm:Signal;

    public function ring():void
    {
        //发布闹钟的响铃事件
        alarm.dispatch();
    }
}
}

再来看看起床类Wakeup.as

package
{
import flash.display.Sprite;

[SWF(width=500,height=300,frameRate=30,backgroundColor=0xFFFFFF)]
/**
 * 测试闹钟
 * @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
 * @author zrong(zengrong.net)
 */
public class Wakeup extends Sprite
{
    public function Wakeup()
    {
        _alarm  = new AlarmClock();

        //向alarm注册事件,这里不需要提供任何的事件名称。因为alarm就是一个确定的Signal实例。
        _alarm.alarm.add(handler_ring);

        //使用addOnce,让alarm在事件收到一次后立即取消
        //_alarm.alarm.addOnce(handler_ring);

        _alarm.ring();
        _alarm.ring();
    }

    private var _alarm:AlarmClock;

    /**
     * 由于我们并没有在事件中传递参数,因此这里的方法也不需要提供任何参数。
     */
    private function handler_ring():void
    {
        trace('起床了!!!');
    }
}
}

在进行事件注册的时候,我们使用的是AlarmClock的public属性alarm。在面向对象编程中,这种方式是不可取的。但我们现在只是个范例对么?不要要求那么严格好不好?

当然,如果你知道在AS3中,使用get方法会比直接使用public属性的性能低不少,或许你也会让这种“不规范”的编程方法延续下去?

取消事件注册

如果运行这个范例,应该可以看到2条“起床了!!!”的trace信息。然后,取消addOnce一行的注释,并注释掉add那行,让它们变成这样:

public function Wakeup()
{
    _alarm  = new AlarmClock();

    //向alarm注册事件,这里不需要提供任何的事件名称。因为alarm就是一个确定的Signal实例。
    //_alarm.alarm.add(handler_ring);

    //使用addOnce,让alarm在事件收到一次后立即取消
    _alarm.alarm.addOnce(handler_ring);

    _alarm.ring();
    _alarm.ring();
}

再次运行范例,应该只能看到1条trace信息了。你可以把这种现象理解成原来的AS事件机制中的removeEventDispatcher被自动执行了。

当然,手动移除也是可以的。如果你使用的是add方法注册,可以使用下面的方法来移除事件的注册。

_alarm.alarm.remove(handler_ring);
_alarm.alarm.removeAll();

传递参数

看看传递参数有多简单吧……修改AlarmClock.as中的相关代码:

public function AlarmClock()
{
    //让我们传递一个AS3的标准Date对象吧,让那个懒虫知道现在几点
    alarm = new Signal(Date);
}

public function ring():void
{
    //把当前的时间发出去
    alarm.dispatch(new Date());
}

再修改Wakeup.as中的相关代码:

private function handler_ring($date:Date):void
{
    trace('起床了!!!也不看看几点了:'+$date.toString());
}

就这样,不需要该死的继承Event和重写clone()了,是不是很清净呢?

Signals框架介绍(二)高级事件

注意:本文参考An introduction to AS3 Signals写成,但不是翻译,有增删改。


也许你现在又想起了AS3内置事件框架的好处,希望使用currentTarget?或者希望支持冒泡?OK,Signals也能满足你那多变的心……(貌似是我自己多变罢了ˇ^ˇ)

高级事件

使用DeluxeSignal可以实现更高级的事件传递。还是基于闹钟的例子进行修改,将原来AlarmClock中的Signal改为DeluxSignal:

[AlarmClock.as]

public function AlarmClock()
{
    //将自己作为引用传递给DeluxeSignal,同时增加GenericEvent的传递
    alarm = new DeluxeSignal(this, GenericEvent, Date);
}

public var alarm:DeluxeSignal;

public function ring():void
{
    alarm.dispatch(new GenericEvent(), new Date());
}

修改Wakeup.as中的处理器函数,让它能够接受到传递的2个参数。

[Wakeup.as]

private function handler_ring($evt:GenericEvent, $date:Date):void
{
    trace('currentTarget:',$evt.currentTarget);
    trace('target:',$evt.target);
    trace('signal:',$evt.signal);
    trace('起床了!!!也不看看几点了:'+$date.toString());
}

在这里出现的GenericEvent,并非继承自flash.events.Event,而是实现了Signals自己的IEvent接口,与AS3的事件机制毫无关系。取一个貌似兄弟的名称,是为了方便大家理解罢了。它所提供的currentTarget和target属性,也是由IEvent自身提供。

运行修改后的例子,可以看到如下输出:

[trace] currentTarget: [object AlarmClock]
[trace] target: [object AlarmClock]
[trace] signal: [object DeluxeSignal]
[trace] 起床了!!!也不看看几点了:Mon Jan 23 17:07:16 GMT+0800 2012

现在,是不是可以对currentTarget“为所欲为”了呢?

冒泡事件

Signals一样可以冒泡,而且并不依赖AS3自带的事件机制。当然,发送和接收冒泡事件的对象必须处于显示列表中。

为了让AlarmClock能够被加入显示列表,我们让AlarmClock继承Sprite。而抛出冒泡事件就非常简单,只需要在实例化GenericEvent的同时传递true参数即可。看看AlarmClock类被修改的部分吧:

[AlarmClock.as]

public class AlarmClock extends Sprite
{
    public function ring():void
    {
        alarm.dispatch(new GenericEvent(true), new Date());
    }
}

接收事件的类,必须实现IBubbleEventHandler接口,在onEventBubbled中处理冒泡事件。同时,要将_alarm实例加入显示列表。

为了方便查看冒泡效果,可以将addOnce所在的一行注释掉,只接收冒泡事件。

[Wakeup.as]

public class Wakeup extends Sprite implements IBubbleEventHandler
{
    public function Wakeup()
    {
        _alarm  = new AlarmClock();
        addChild(_alarm);
        //_alarm.alarm.addOnce(handler_ring);
        _alarm.ring();
    }

    public function onEventBubbled($evt:IEvent):Boolean
    {
        trace('冒泡 currentTarget:',$evt.currentTarget);
        trace('冒泡 target:',$evt.target);
        trace('冒泡 signal:',$evt.signal);
        //返回false代表不再继续冒泡
        return false;
    }
}

运行修改后的例子,可以看到如下输出:

[trace] 冒泡 currentTarget: [object Wakeup]
[trace] 冒泡 target: [object AlarmClock]
[trace] 冒泡 signal: [object DeluxeSignal]

完整的类

[AlarmClock.as]

package
{
import flash.display.Sprite;
import org.osflash.signals.Signal;
import org.osflash.signals.DeluxeSignal;
import org.osflash.signals.events.GenericEvent;

/**
* Signals闹钟范例
* @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
* @author zrong(zengrong.net)
*/

public class AlarmClock extends Sprite
{
    public function AlarmClock()
    {
        alarm = new DeluxeSignal(this, GenericEvent, Date);
    }

    public var alarm:DeluxeSignal;

    public function ring():void
    {
        //使用冒泡的方式发布闹钟的响铃事件
        alarm.dispatch(new GenericEvent(true), new Date());
    }
}
}
</pre>

**[Wakeup.as]**

<pre lang="ActionScript" line="1" coloa="+">
package
{
import flash.display.Sprite;
import org.osflash.signals.events.GenericEvent;
import org.osflash.signals.events.IBubbleEventHandler;
import org.osflash.signals.events.IEvent;

[SWF(width=500,height=300,frameRate=30,backgroundColor=0xFFFFFF)]
/**
 * 测试闹钟
 * @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
 * @author zrong(zengrong.net)
 */
public class Wakeup extends Sprite implements IBubbleEventHandler
{
    public function Wakeup()
    {
        _alarm  = new AlarmClock();
        addChild(_alarm);
        _alarm.alarm.addOnce(handler_ring);
        _alarm.ring();
    }

    private var _alarm:AlarmClock;

    private function handler_ring($evt:GenericEvent, $date:Date):void
    {
        trace('currentTarget:',$evt.currentTarget);
        trace('target:',$evt.target);
        trace('signal:',$evt.signal);
        trace('起床了!!!也不看看几点了:'+$date.toString());
    }

    public function onEventBubbled($evt:IEvent):Boolean
    {
        trace('冒泡 currentTarget:',$evt.currentTarget);
        trace('冒泡 target:',$evt.target);
        trace('冒泡 signal:',$evt.signal);
        //返回false代表不再继续冒泡
        return false;
    }
}
}

pureMVC实现、术语阐述及最佳实践(中文版)

pureMVC的官方文档,介绍pureMVC用法、特点、结构。
介绍 下载

我已经使用pureMVC2个月左右,感觉确实是很不错的框架,上手也不难,当时是看了几个官方范例之后就开始动手改原来写的项目了。强烈推荐!

[转]23种设计模式中英文对照

  1. Singleton 单件模式
  2. Abstract Factory 抽象工厂模式
  3. Builder 生成器模式
  4. Factory Method 工厂方法模式
  5. Prototype 原型模式
  6. Adapter 适配器模式
  7. Bridge 桥接模式
  8. Composite 组合模式
  9. Decorator 装饰模式
  10. Facade 外观模式
  11. Flyweight 享元模式
  12. Proxy 代理模式
  13. Template Method模板方法
  14. Command 命令模式
  15. Interpreter 解释器模式
  16. Mediator 中介者模式
  17. Iterator 迭代器模式
  18. Observer 观察者模式
  19. Chain Of Responsibility 职责链模式
  20. Memento 备忘录模式
  21. State 状态模式
  22. Strategy 策略模式
  23. Visitor 访问者模式

转自