最近我在研究下一代的客户端界面编程技术,就是研究Flex和JavaFX这两种新语言。
Java,C#,JavaFX,Flex等语言都有事件处理机制。 事件处理机制 实际上就是GOF23设计模式中的Observer观察者模式的实现。
Flex的事件处理机制,使用了方法作为事件处理器。这和C#的委派相似。因为Flex继承了JavaScript的特性,方法对象,就是方法的指针。类似于C语言的函数指针。
而C#中使用了delegete这个语法糖,实现了函数指针。尽管其底层实际上是使用了反射的Method对象。
Java中由于没有函数指针的概念,所以其事件处理器是接口。
尽管Java语言也可以使用反射中的Method对象来构建出函数指针。但是Java的官方解决方案没有采用这种措施。
Flex声明事件时,是这样做的:
1,事件源
2,事件类型-----一个String
3,响应事件的函数指针
这个机制和Java的非常类似。
Java是这样子的:
1,事件源
2,Command------一个String
3,响应事件的接口
但是又有不同,Java语言中,事件源有一个List,用于保存事件监听器接口对象。
然后,激发事件时调用List中所有的接口的相应函数。
在激发事件时,创建事件对象,对象中包括:事件源----就是自己,Command-----一个自定义的字符串。
然后事件处理器接口中的响应函数根据事件对象中的Command来决定怎样处理。
Flex的事件处理机制略有不同,应该说是有改进:
1,事件源中有一个Map<String,List<函数指针>>,而不是List。 响应事件的函数对象被根据事件类型----一个自定义的String而分开储存。
这样,激发事件时,根据需要事件类型,直接激发Map中的一组事件。而不是调用所有注册的事件监听器。
同时,注意Flex的以下特性:
1,Flex不支持内部类。但是由于不使用接口,而只是使用函数。因此,不支持内部类的这一特性不会对Flex的事件处理机制造成任何不良影响。
2,Flex支持函数内部嵌套函数,支持不属于类的函数和变量。因此,编写响应事件的函数是非常方便的。
下面是Flex事件处理机制的一个例子,用于实现MVC模式的界面开发。
1,作为Model的类,使用了Flex的事件机制,作为事件源。在value改变时通知事件响应函数,用于更改View界面。
package{
import flash.events.*;
public class MyModel implements IEventDispatcher {
public function MyModel(){
this.eventDispatcher=new EventDispatcher(this);
}
private var eventDispatcher;
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
this.eventDispatcher.addEventListener(type,listener,useCapture,priority,useWeakReference);
}
public function dispatchEvent(event:Event):Boolean {
return this.eventDispatcher.dispatchEvent(event);
}
public function hasEventListener(type :String):Boolean {
return this.eventDispatcher.hasEventListener(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
this.eventDispatcher.removeEventListener(type,listener,useCapture);
}
public function willTrigger(type :String):Boolean {
return this.eventDispatcher.willTrigger(type);
}
///////////////////////////////////////////事件//////////////
private var myValue;
public function set value(v){
this.myValue=v;
this.dispatchEvent(new Event("changeValue"));
}
public function get value(){
return this.myValue;
}
}
}
2,用户界面,是一个文本输入框,一个文本输出框。
输入框的更改,立刻反应到文本输出框中。
3,用户界面的处理代码:
var myModel=new MyModel;
myModel.addEventListener("changeValue",responseChangeValue);
function responseChangeValue(event:Event):void{
mainText.text=event.target.value;
}
inputText.border=true;
inputText.addEventListener(flash.events.Event.CHANGE , inputTextChange);
function inputTextChange(event:Event):void
{
myModel.value=event.target.text;
}
接下来讲一下JavaFX的事件处理机制。
JavaFX使用触发器来实现事件处理:
触发器的语法格式为:
"on" "replace"
[oldValue]
[ "[" lowIndex ".." highIndex "]" "=" newElements ]
代码块
当对关联的变量进行修改的时候,触发器就会被执行。参数定义如下:
· oldValue 是变量的原值
· lowIndex, highIndex,是数组类型的触发器才有的参数,都是整数类型的。对于插入操作,highIndex==lowIndex-1。
· newElements 是新的值数组,这个数组是用来替换oldValue[lowIndex..highIndex]的,类型和变量相同。
[lowIndex..highIndex]=newElements 部分的参数,只有变量为一个数组的时候才有。
等同于:
attribute x =
on replace [i..j]=n
{ y[i..j]=n };
attribute y = [];
这样就在数组x的数据变化时,把数组y的值改成数组x的值。
另外还有bind语法作为触发器的语法糖。
attribute x;
attribute y = bind x;
这可以实现同样的效果。
JavaFX是一种专注于GUI的脚本语言,有很多新颖的语言概念。比如上面javaFX的事件处理机制就很简约、强大。