Java設(shè)計(jì)模式——事件驅(qū)動(dòng)模式(觀察者模式)
角色
- 事件
- 事件源
- 事件監(jiān)聽(tīng)器
事件
事件類一般繼承自java.util.EventObject類,封裝了事件源以及跟事件有關(guān)的信息
source:事件源
getSource():獲取事件源
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* The object on which the Event initially occurred
*/
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public Object getSource() {
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
事件源
每個(gè)事件包含一個(gè)事件源,事件源是事件發(fā)生的地方,由于事件源的某項(xiàng)屬性或狀態(tài)改變時(shí),就會(huì)生成相應(yīng)的事件對(duì)象,然后將事件對(duì)象通知給所有監(jiān)聽(tīng)該事件源的監(jiān)聽(tīng)器。
事件監(jiān)聽(tīng)器
事件監(jiān)聽(tīng)器一般需要實(shí)現(xiàn)java.util.EventListener接口
public interface EventListener {
}
EventListener 是個(gè)空接口,監(jiān)聽(tīng)器必須要有回調(diào)方法供事件源回調(diào),這個(gè)回調(diào)方法可以在繼承或者實(shí)現(xiàn)EventListener 接口的時(shí)候自定義。
實(shí)現(xiàn)源碼
-
事件監(jiān)聽(tīng)器:事件監(jiān)聽(tīng)器可以直接實(shí)現(xiàn)
EventListener接口,但是一般框架會(huì)有自己的監(jiān)聽(tīng)器接口,所以這里先繼承EventListener接口public interface ApplicationListener extends EventListener{ void onApplicationEvent(ApplicationListener event); } -
事件:事件類可以直接使用
EventObject,這里通過(guò)繼承EventObject類實(shí)現(xiàn)自己的事件類public class ApplicationEvent extends EventObject { /** * Constructs a prototypical Event. * * @param source The object on which the Event initially occurred. * @throws IllegalArgumentException if source is null. */ public ApplicationEvent(Object source) { super(source); } } -
運(yùn)行上下文環(huán)境
public class ApplicationContext { /** * 存放所有的監(jiān)聽(tīng)器 */ Set<ApplicationListener> listeners; public ApplicationContext() { this.listeners = new HashSet<>(); } /** * 添加監(jiān)聽(tīng)器 * @param listener 監(jiān)聽(tīng)器 */ public void addApplicationListener(ApplicationListener listener) { this.listeners.add(listener); } /** * 發(fā)布事件 * 回調(diào)所有監(jiān)聽(tīng)器的回調(diào)方法 * @param event 事件 */ public void publishEvent(ApplicationEvent event) { for (ApplicationListener listener : listeners) { listener.onApplicationEvent(event); } } } -
測(cè)試類
public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new ApplicationContext(); /** * 添加監(jiān)聽(tīng)事件源為整型的監(jiān)聽(tīng)器 */ applicationContext.addApplicationListener(event -> { Object source = event.getSource(); if (source instanceof Integer) { int now = (int) source; System.out.println("檢測(cè)到事件源為整型:事件源變?yōu)? + now); } }); /** * 添加監(jiān)聽(tīng)事件源為字符串類型的監(jiān)聽(tīng)器 */ applicationContext.addApplicationListener(event -> { Object source = event.getSource(); if (source instanceof String) { String now = (String) source; System.out.println("檢測(cè)到事件源為字符串類型:事件源變?yōu)? + now); } }); /** * 發(fā)布事件 */ // applicationContext.publishEvent(new ApplicationEvent(1001)); applicationContext.publishEvent(new ApplicationEvent("Hello")); } } -
輸出
檢測(cè)到事件源為字符串類型:事件源變?yōu)镠ello
Spring事件驅(qū)動(dòng)
spring的事件驅(qū)動(dòng)和上面的實(shí)現(xiàn)方式有些不同,最大的區(qū)別是監(jiān)聽(tīng)器的添加方式,spring一般的添加方式是實(shí)現(xiàn)ApplicationListener接口,然后把實(shí)現(xiàn)類注冊(cè)為Bean,spring的上下文初始化的時(shí)候會(huì)自動(dòng)掃描路徑下的實(shí)現(xiàn)ApplicationListener接口的類,然后添加到監(jiān)聽(tīng)器集合里面,發(fā)布事件的時(shí)候會(huì)通知所有的監(jiān)聽(tīng)器,這一切要依賴spring的容器管理Bean的功能。