事件机制的三个角色
- 事件源,表示事件发生的起源
- 事件对象,持有一个事件源
- 事件处理的监听器,事件发生时具体的处理回调,需要用户去实现这个接口
在Java AWT中,事件机制广泛应用。我们将模仿点击事件,构建完整的源->触发->处理过程。UML类图如下:
image.png
首先,创建一个事件对象。
import java.util.EventObject;
public class ClickEvent extends EventObject {
private EventSource src;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @throws IllegalArgumentException if source is null.
*/
public ClickEvent(EventSource source) {
super(source);
this.src = source;
}
}
ClickEvent
继承自EventObject
,持有一个EventSource
的引用,在构造点击事件时必须指明事件源。
事件源定义:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
public class EventSource {
private Semaphore semaphore = new Semaphore(1);
private final List<ClickEventListener> listeners = new ArrayList<>();
public void addListener(ClickEventListener listener) throws InterruptedException {
semaphore.acquire(1);
listeners.add(listener);
semaphore.release(1);
}
public void removeListener(ClickEventListener listener) throws InterruptedException {
semaphore.acquire(1);
if(!listeners.isEmpty())
listeners.remove(listener);
semaphore.release(1);
}
protected void actionPerformed() throws InterruptedException {
semaphore.acquire(1);
ClickEvent event = new ClickEvent(this);
for (ClickEventListener listener : listeners) {
listener.click(event);
}
semaphore.release(1);
}
}
事件源可以添加一组监听器,绑定的一组监听器在事件触发之后,会将监听器的具体动作逐一执行。
定义一个简单的点击事件监听器:
public interface ClickEventListener extends EventListener {
void click(ClickEvent e);
}
ClickEventListener
继承自EventListener
,查看源码发现EventListener
是一个空接口,因此定义的事件监听器将是一个SAM interface,如果还不清楚SAM interface的概念,请查看我之前的一篇文章Functional Programming in Java 8,因此可以使用lambda表达式来实现这个监听器接口。
最后,我们需要完成一次完整的调用处理:
public class Main {
public static void main(String[] args) {
EventSource source = new EventSource();
try {
source.addListener((e) -> System.out.println("Click event performed!"));
source.actionPerformed();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
事件处理机制在某种程度上与发布-订阅模式非常相似,事件监听器的角色与观察者类似,事件源则充当了被观察对象。事件源状态触发后,主动发起通知给监听器,监听器完成各种后续处理。
网友评论