成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

監聽器模式和觀察者模式的關系,寫點你不知道的

安全 應用安全
通過本篇文章我們知道,監聽器模式的本質就是觀察者模式,先將回調函數注冊到被觀察對象,當被觀察對象發生變化時,通過回調函數告知觀察者/監聽者。而Spring中事件管理也是基于觀察者模式實現的,算是一個比較經典的案例。

[[404308]]

本文轉載自微信公眾號「程序新視界」,作者二師兄。轉載本文請聯系程序新視界公眾號。

前言

無論大家在實踐中是否自己實現過觀察者模式或監聽器模式,但肯定間接使用過。比如Spring的事件機制,大多數人肯定都用過,只是沒留意而已。

今天這篇文章主要圍繞觀察者模式、監聽器模式,以及它們之間的關系展開。不僅用實例介紹它們的使用,而且也會聊一聊Spring事件機制對觀察者模式的實踐。

監聽器模式和觀察者模式怎么看起來是一樣的?

先聊聊設計模式

為什么要使用監聽模式,直接調用不好嗎?這我們就要說說設計模式的好處了。設計模式(Design pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。同時,采用設計模式之后,代碼能夠達到低耦合、低依賴的效果。

也就是說,即便不用設計模式,直接硬編碼也能實現。但如果考慮到代碼的耦合性、依賴性、擴展性等問題,設計模式便是更好的選擇。比如觀察者模式就能達到解耦、異步等效果。

觀察者模式的定義

觀察者模式定義了對象之間的一對多依賴,即一個主題對應多個觀察者。當一個主題對象改變狀態時,它的所有依賴者(觀察者)都會收到通知并自動更新。比如用戶訂閱某個訂閱號或公眾號,當發新消息時,會發送給所有訂閱者。

觀察者模式解決的是對象和對象之間的依賴關系。當多個對象依賴一個對象的關系時,一個主題對象狀態改變,需要通知所有觀察者對象。

監聽器模式并不是一個新的設計模式,它是觀察者模式在特定場景下的一種改造和應用。通常,觀察者模式的主題在通知觀察者時,通知中不包含任何信息。如果這個過程中攜帶了一些其他信息,那么主題本身就成為了事件源,而攜帶信息的封裝類就成為了事件。此時的觀察者模式,也就升級為監聽器了。監聽器模式是觀察者模式的另一種形態。

觀察者模式實例

先來看看觀察者模式的代碼實現,可以直接使用JDK自帶的Observer,也可以自定義對應的API。單從JDK自帶觀察者模式的API,也可以看出該設計模式的分量(雖然在Java被廢棄了)。

我們這里采用自定義相關類,主要包括主題和觀察者兩種對象。

首先定義一個主題對應的接口Subject:

  1. public interface Subject { 
  2.  
  3.     /** 
  4.      * 注冊定義 
  5.      */ 
  6.     void registerObserver(Observer observer); 
  7.  
  8.     /** 
  9.      * 發送通知 
  10.      */ 
  11.     void notifyObservers(Object msg); 
  12.  

主題接口中定義了兩個方法一個用來注冊觀察者,一個用來發送通知。定義這個主題的具體實現類ConcreteSubject:

  1. public class ConcreteSubject implements Subject { 
  2.  
  3.     /** 
  4.      * 觀察者集合 
  5.      */ 
  6.     private List<Observer> observers = new ArrayList<>(); 
  7.  
  8.     @Override 
  9.     public void registerObserver(Observer observer) { 
  10.         // 添加訂閱關系 
  11.         observers.add(observer); 
  12.     } 
  13.  
  14.     @Override 
  15.     public void notifyObservers(Object msg) { 
  16.         // 通知訂閱者 
  17.         for (Observer observer : observers) { 
  18.             observer.update(msg); 
  19.         } 
  20.     } 

實現類中存儲了,觀察者的集合,這樣就實現了主題和觀察者之間一對多的關系。

創建一個觀察者接口Observer,方便管理:

  1. public interface Observer { 
  2.     // 處理業務邏輯 
  3.     void update(Object msg); 

定義觀察者接口的具體實現類ConcreteObserver:

  1. public class ConcreteObserver implements Observer { 
  2.  
  3.     @Override 
  4.     public void update(Object msg) { 
  5.         // 業務邏輯實現 
  6.         System.out.println("ConcreteObserver 接收到主題的消息: " + msg); 
  7.     } 

在實現類中,打印一行消息。當然,在實踐的過程中,這個實現類可以通過匿名類的形式創建,這樣就具體的匿名類就在registerObserver時定義了。

下面來測試一下:

  1. public class ConcreteObserver implements Observer { 
  2.  
  3.     @Override 
  4.     public void update(Object msg) { 
  5.         // 業務邏輯實現 
  6.         System.out.println("ConcreteObserver 接收到主題的消息: " + msg); 
  7.     } 

執行程序,打印結果:

  1. ConcreteObserver 接收到主題的消息: 來自Subject的消息 

說明可以正常接收到主題發布的消息。

在上面的實現中,可以看出已經達到了解耦合的效果,同時減少了依賴關系。每個觀察者根本不需要知道發布者處理了什么業務邏輯,也不依賴于發布者的業務模型,只關心自己的邏輯處理即可。

監聽模式實例

監聽器模式通常包含三個角色:事件源、事件對象、事件監聽器。如果觀察者模式中的類名和方法對照改一下,并不改變業務邏輯,我們來看看是啥效果。

比如,將Observer改名為Listener,將其update方法改為onClick();將Subject的實現類ConcreteSubject改名為ListenerSupport,將registerObserver方法更名為addListener……

定義一個事件對象Event,用來傳遞事件信息:

  1. public class Event { 
  2.     private String data; 
  3.     private String type; 
  4.  
  5.     Event(String data, String type) { 
  6.         this.data = data; 
  7.         this.type = type; 
  8.     } 
  9.     // 省略getter/setter 

原來主題的訂閱對象Observer改名為Listener之后,成為監聽器:

  1. public interface Listener { 
  2.     void onClick(Event event); 

為監聽器提供一個實現類,當然在實踐中也可以采用匿名類創建的方式:

  1. public class ListenerA implements Listener { 
  2.  
  3.     @Override 
  4.     public void onClick(Event event) { 
  5.         System.out.println("觸發事件,type:" + event.getType() + ",data:" + event.getData()); 
  6.     } 

原來的主題ConcreteSubject對照ListenerSupport成為事件管理器:

  1. public class ListenerSupport { 
  2.  
  3.     private List<Listener> listeners = new ArrayList<>(); 
  4.  
  5.     public void addListener(Listener listener) { 
  6.         listeners.add(listener); 
  7.     } 
  8.  
  9.     public void triggerEvent(Event event) { 
  10.         for (Listener listener : listeners) { 
  11.             listener.onClick(event); 
  12.         } 
  13.     } 

對應的測試代碼:

  1. public class EventTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.         Listener listener = new ListenerA(); 
  5.         ListenerSupport listenerSupport = new ListenerSupport(); 
  6.         listenerSupport.addListener(listener); 
  7.         listenerSupport.triggerEvent(new Event("dataA""typeA")); 
  8.     } 

執行程序,打印信息如下:

  1. 觸發事件,type:typeA,data:dataA 

通過上面的對照代碼,我們可以看出,即便業務邏輯不變,經過重命名的觀察者模式已經變為監聽器模式了。而它們的對照關系是:事件源對照ConcreteSubject(主題)、事件對象對照update方法的Object、事件監聽器對照ConcreteObserver(訂閱者)。這也再次證明了所說的“監聽器模式是觀察者模式的另一種形態”。

觀察者模式和監聽器模式對比

用一張圖,來比較觀察者模式和監聽器模式的聯系和區別:

通過對比可以發監聽器模式的優勢是:在很多場景中,通知中附帶了一些必不可少的其他信息,而事件Event可以對這些信息進行封裝,使它本身擁有了多態的特性。每個事件對象就可以包含不同的信息。從這個層面來說,事件監聽器模式是對觀察者模式進行了進一步的抽象。

Spring中的最佳實踐

觀察者模式的經典應用算是Spring事件驅動模型了,它便是基于觀察者模式實現的,同時也是項目中最常見的事件監聽器。

Spring中觀察者模式包含四個角色:事件、事件監聽器、事件源、事件管理。

事件:ApplicationEvent是所有事件對象的父類。ApplicationEvent繼承自jdk的EventObject,所有的事件都需要繼承ApplicationEvent,并且通過source得到事件源。Spring 提供了很多內置事件,比如:ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent。

事件監聽器:ApplicationListener,也就是觀察者,繼承自jdk的EventListener,該類中只有一個方法onApplicationEvent,當監聽的事件發生后該方法會被執行。

事件源:ApplicationContext,ApplicationContext是Spring的核心容器,在事件監聽中ApplicationContext可以作為事件的發布者,也就是事件源。因為ApplicationContext繼承自ApplicationEventPublisher。在ApplicationEventPublisher中定義了事件發布的方法:publishEvent(Object event)。

事件管理:ApplicationEventMulticaster,用于事件監聽器的注冊和事件的廣播。監聽器的注冊就是通過它來實現的,它的作用是把Applicationcontext發布的Event廣播給它的監聽器列表。

小結

 

通過本篇文章我們知道,監聽器模式的本質就是觀察者模式,先將回調函數注冊到被觀察對象,當被觀察對象發生變化時,通過回調函數告知觀察者/監聽者。而Spring中事件管理也是基于觀察者模式實現的,算是一個比較經典的案例。

 

責任編輯:武曉燕 來源: 程序新視界
相關推薦

2022-01-29 22:12:35

前端模式觀察者

2020-10-26 08:45:39

觀察者模式

2021-09-06 10:04:47

觀察者模式應用

2021-07-08 11:28:43

觀察者模式設計

2013-11-26 17:09:57

Android設計模式

2011-04-29 09:22:22

2024-06-04 13:11:52

Python行為設計模式開發

2024-12-03 09:34:35

觀察者模 式編程Javav

2021-07-08 07:52:49

容器監聽器Event

2022-05-09 10:50:13

觀察者模式設計模式

2024-02-18 12:36:09

2015-11-25 11:10:45

Javascript設計觀察

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2012-08-27 10:52:20

.NET架構觀察者模式

2021-03-29 07:14:28

Spring觀察者模式

2009-03-30 09:39:04

觀察者思想換位設計模式

2021-10-22 09:41:26

橋接模式設計

2022-11-15 07:35:50

Spring事件觀察者模式

2011-09-15 17:10:41

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久综合久久久 | 欧美一区二区三 | 少妇一级淫片免费放播放 | 亚洲国产成人久久综合一区,久久久国产99 | av毛片| 日日骚视频 | 久久99精品久久久久久青青日本 | 久久人爽爽人爽爽 | 麻豆精品国产免费 | 爱综合 | 91伊人| 国产日韩精品视频 | 成人一区二区三区 | 三级黄色大片网站 | 天天天天操 | 在线日韩| 一级片视频免费 | 久久精品91久久久久久再现 | 中文日韩在线视频 | 免费在线观看一区二区 | 免费av直接看 | 欧美综合一区二区 | 国产成人精品免高潮在线观看 | 在线激情视频 | 成人免费视频网站在线观看 | 视频一区二区在线观看 | 99免费在线视频 | 国产精品久久久99 | 精产国产伦理一二三区 | 又黄又色| www.日本在线观看 | 在线观看国产wwwa级羞羞视频 | 久久国产视频播放 | 91 视频网站 | 欧美一卡二卡在线 | 欧美一区 | 成年人免费网站 | 国产精品一区久久久 | 玖玖免费| 国产乱码精品一区二三赶尸艳谈 | 免费毛片在线 |