这篇文章主要介绍了浅谈用java实现事件驱动机制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
由于项目需求,需要为java提供一套支持事件驱动机制的类库,可以实现类似于c#中的event和delegate机制。众所周知,java语言本身以及其标准库中并没有提供事件驱动机制的相关接口,虽然swing(我且认为其不属于标准库,因为一般没人用:)中存在相关的类支持该机制以实现组件的事件处理,但它毕竟是与gui相耦合的,而在其它类型的应用程序中使用起来显得就有些别扭,缺乏通用性。因此有必要实现一套通用的java事件驱动机制类库,然后将其应用于通用的java应用程序当中,虽然这并不是什么难事:)
让我们先考察一下c#的事件驱动机制编写方法。c#中提供的event关键字可以很容易的用来定义一个事件,然后通过向事件中添加事件处理函数(在c#中一般用委托(delegate)来引用一个函数),触发事件就可以调用相关的处理函数,也即是事件驱动的过程。例如:
//定义事件和对应的委托
public event mydelegate click;
public delegate void mydelegate();
//定义委托
void onclick(){
console.writeline("you just clicked me!");
}
//将委托与事件关联
click += onclick;
//触发事件
click();
上面的代码就是用c#实现的事件驱动机制的一个简单的例子,可见是非常简单的,这都源于c#在语言层面(其实是clr)提供的便利。遗憾的是java并不提供这样的便利,需要人为去实现。下面本文将提供两种实现事件驱动机制的方法,仅供参考。
观察者模式
观察者模式是一种常用的设计模式,观察者(observer)先通过订阅被观察对象(subject),这样一旦被观察者(subject)发生某种变化,就会将变化通知观察者(observer)。
这种设计模式刚好可以用于事件驱动机制,事件(event)相当于被观察对象(subject),一旦事件被触发,就会调用事件处理函数,可见事件处理函数(c#中的委托)可以看作是观察者。因此可以像如下这样实现上文中的功能。
/*事件类*/
public event {
//与事件相关的事件处理函数
public arraylist<callback> callbacklist;
//事件触发函数
public void emit(){
for(callback cb : callbacklist){
cb.run();
}
}
//注册事件处理函数
public registercallback(callback cb){
callbacklist.add(cb);
}
}
/*事件处理函数类*/
public interface callback {
void run();
}
public onclick implements callback {
//函数
public void run(){
system.out.println("you just clicked me!");
}
/*实现事件驱动*/
event e = new event();
//将onclick事件处理函数注册到事件中
e.registercallback(new onclick());
//触发事件
e.emit();
上面的java代码实现了一种简单的事件驱动机制,原理很简单,是一种典型的观察者模式的应用案例。
利用反射
java语言提供强大的反射功能,可以在运行时获取类的各个组成部分(比如类名、类成员函数、类属性等等)并对其进行操作。下面使用反射来实现简单的事件驱动机制。
/*事件处理类*/
public class eventhandler {
//事件源
private object sender;
//事件处理函数名称(用于反射)
private string callback;
public eventhandler(object sender, string callback){
this.sender = sender;
this.callback = callback;
}
//事件触发
public void emit(){
class sendertype = this.sender.getclass();
try {
//获取并调用事件源sender的事件处理函数
method method = sendertype.getmethod(this.callback);
method.invoke(this.sender);
} catch (exception e2) {
e2.printstacktrace();
}
}
}
/*事件源*/
public class button(){
/*可以在此设置button类的相关属性,比如名字等*/
private string name;
...
//事件处理函数
public void onclick(){
system.out.println("you just clicked me!");
}
}
/*实现事件驱动机制*/
button b = new button();
if(/*收到按钮点击信号*/){
eventhandler e = new eventhandler(b, "onclick");
e.emit();
}
上述代码展示了利用反射实现的事件驱动机制,利用反射机制的好处是其具有强大的扩展性,比如我的事件处理函数中可以引入一个eventargs的形参,从而可以让事件本身带有参数,这样就可以让事件携带更多的信息,改写后的事件处理函数如下方的代码所示:
public class eventargs {
//参数
string p1;
integer p2;
...
}
//onclick事件处理函数改写
public void onclick(object sender, eventargs e){
//参数e提供更多的信息
system.out.println("hello, you clicked me! " + e.p1 + e.p2);
}
//触发函数emit改写
public void emit(eventargs e){
class sendertype = this.sender.getclass();
try {
//获取并调用事件源sender的事件处理函数
method method = sendertype.getmethod(this.callback, this.getclass(), e.getclass());
method.invoke(this.sender, this.sender, e);
} catch (exception e2) {
e2.printstacktrace();
}
}
是不是似曾相识?没错,和用c#写winform窗体时,visual studio为你自动生成的事件处理函数(代码中的onclick函数)几乎具有完全相同的形式,但此时我们是用java实现的。
当然,除了以上提到的两种方法可以实现java的事件驱动机制以外,还有一些其它的方法,比如可以利用java的内部类来实现,笔者也曾写过一些示例代码,这里就不再冗言了,留待以后再讲。
以上就是java如何实现事件驱动机制的实例的详细内容。