Java設(shè)計(jì)模式:事件驅(qū)動(dòng)模式(觀察者模式)

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的功能。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 事件和平時(shí)所用的回調(diào)思想在與GUI(JavaScript,Swing)相關(guān)的技術(shù)中非常流行。而在Web應(yīng)用程序的服...
    Java小鋪閱讀 1,146評(píng)論 0 0
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,659評(píng)論 19 139
  • 文章較長(zhǎng),建議先收藏,在較空的時(shí)候來(lái)看。 Spring Boot 框架的初衷:快速地啟動(dòng)Spring應(yīng)用Sprin...
    Drew_Zhong閱讀 2,882評(píng)論 3 15
  • 2018燕郊高新區(qū)少兒才藝大賽啟動(dòng)儀式于5月19日在銀河灣青少年文化廣場(chǎng)隆重舉行?;顒?dòng)當(dāng)天,主辦方的多位領(lǐng)導(dǎo)、承辦...
    A3Know閱讀 492評(píng)論 0 0
  • 佛曰:一花一世界,一木一浮生,一草一天堂,一葉一如來(lái),一砂一極樂(lè),一方一凈土,一笑一塵緣,一念一清凈。人們的普遍觀...
    鈐魚(yú)擺擺閱讀 450評(píng)論 2 1

友情鏈接更多精彩內(nèi)容