您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

03 java 訂閱者模式(java設計模式-回調、事件監聽器、觀察者模式)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-05-18 07:14:26【】1人已围观

简介方法,從而對剩余的邏輯有不同的實現。先制定一個頂級邏輯框架,而將邏輯的細節留給具體的子類去實現。23、VISITOR?情人節到了,要給每個MM送一束鮮花和一張卡片,可是每個MM送的花都要針對她個人的特

方法,從而對剩余的邏輯有不同的實現。先制定一個頂級邏輯框架,而將邏輯的細節留給具體的子類去實現。

23、VISITOR?情人節到了,要給每個MM送一束鮮花和一張卡片,可是每個MM送的花都要針對她個人的特點,每張卡片也要根據個人的特點來挑,我一個人哪搞得清楚,還是找花店老板和禮品店老板做一下Visitor,讓花店老板根據MM的特點選一束花,讓禮品店老板也根據每個人特點選一張卡,這樣就輕松多了; 訪問者模式:訪問者模式的目的是封裝一些施加于某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構可以保持不變。訪問者模式適用于數據結構相對未定的系統,它把數據結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化。訪問者模式使得增加新的操作變的很容易,就是增加一個新的訪問者類。訪問者模式將有關的行為集中到一個訪問者對象中,而不是分散到一個個的節點類中。當使用訪問者模式時,要將盡可能多的對象瀏覽邏輯放在訪問者類中,而不是放到它的子類中。訪問者模式可以跨過幾個類的等級結構訪問屬于不同的等級結構的成員類。

觀察者模式(Observer Pattern)

觀察者模式又稱為發布訂閱模式。一個發布者對應多個訂閱者,一旦發布者的狀態發生改變時,訂閱者將收到訂閱事件。

先看看一個生活中的例子:

我們使用想瀏覽Java相關的文章,于是我們點擊訂閱了[Java專題],當[Java專題]有新文章發布就會推送給我們,當然其他人也可以訂閱[Java專題]并收到[Java專題]的推送。這就是觀察者。 定義對象間的一對多關系,當一個對象的狀態發生變化時,所依賴于它的對象都得到通知并主動更新。在觀察者模式中,多個訂閱者成為觀察者(Observer),被觀察的對象成為目標(Subject)。

實現觀察者模式的方法不只一種,但是以包含Subject與Observer接口的類設計的做法最常見。(Java API 內置觀察者模式用的是Observer接口與Observable類)

觀察者模式UML圖:

先定義觀察者模式的接口

在觀察者模式的實現上,有推模式和拉模式兩種方式。

上面例子中

void updateByPush(Object obj) 就是推模式;

void updateByPull(Subject subject)就是拉模式

java.util包內包含最基本的Observer接口與Observable類(其實對應的就是Subject類)

我們看一下Observer源碼

我們看到update更新方法有兩個參數:Observable、Object,可見Java API 內置觀察者模式同時支持[拉]和[取]

我們再來看看Observable類源碼

注意Observable是一個類,而不是接口,這有一定的局限性。因為如果某個類想同時具有Observable類和另一個超類的行為,就會陷入兩難,畢竟Java不支持多重繼承。

有點需要特別提一下的就是,Java API 內置的Observable需要調用一下 setChanged();觀察者才能收到推送,我們看一下源碼,發現notifyObservers方法里有判斷changed的狀態為true才去通知觀察者。

我們自己實現觀察者模式的時候是沒有這一點的,那加上這一個標志位有什么好處?好處就是更靈活,Observable類只提供這個boolean值來表明是否發生變化,而不定義什么叫變化,因為每個業務中對變化的具體定義不一樣,因此子類自己來判斷是否變化;該變量既提供了一種抽象(變與不變),同時提供了一種觀察者更新狀態的可延遲加載,通過后面的notifyObservers方法分析可知觀察者是否會調用update方法,依賴于changed變量,因此即使被觀察者在邏輯上發生改變了,只要不調用setChanged,update是不會被調用的。如果我們在某些業務場景不需要頻繁觸發update,則可以適時調用setChanged方法來延遲刷新。

阿里云折扣快速入口

java設計模式-回調、事件監聽器、觀察者模式

轉自( 買粉絲s://my.os買粉絲.買粉絲/u/923324/blog/792857 )

背景

關于設計模式,之前筆者寫過工廠模式,最近在使用gava ListenableFuture時發現事件監聽模型特別有意思,于是就把事件監聽、觀察者之間比較了一番,發現這是一個非常重要的設計模式,在很多框架里扮演關鍵的作用。

回調函數

為什么首先會講回調函數呢?因為這個是理解監聽器、觀察者模式的關鍵。

什么是回調函數

所謂的回調,用于回調的函數。 回調函數只是一個功能片段,由用戶按照回調函數調用約定來實現的一個函數。 有這么一句通俗的定義:就是程序員A寫了一段程序(程序a),其中預留有回調函數接口,并封裝好了該程序。程序員B要讓a調用自己的程序b中的一個方法,于是,他通過a中的接口回調自己b中的方法。

舉個例子:

這里有兩個實體:回調抽象接口、回調者(即程序a)

回調接口(ICallBack )

public interface ICallBack {

public void callBack();

}

回調者(用于調用回調函數的類)

public class Caller {

}

回調測試:

public static void main(String[] args) {

Caller call = new Caller();

call.call(new ICallBack(){

控制臺輸出:

start...

終于回調成功了!

end...

還有一種寫法

或實現這個ICallBack接口類

class CallBackC implements ICallBack{

@Override

public void callBack() {

System.out.println("終于回調成功了!");

}

}

有沒有發現這個模型和執行一個線程,Thread很像。 沒錯,Thread就是回調者,Runnable就是一個回調接口。

new Thread(new Runnable(){

@Override

public void run() {

System.out.println("回調一個新線程!");

}}).start();

Callable也是一個回調接口,原來一直在用。 接下來我們開始講事件監聽器

事件監聽模式

什么是事件監聽器

監聽器將監聽自己感興趣的事件一旦該事件被觸發或改變,立即得到通知,做出響應。例如:android程序中的Button事件。

java的事件監聽機制可概括為3點:

java的事件監聽機制涉及到 事件源,事件監聽器,事件對象 三個組件,監聽器一般是接口,用來約定調用方式

當事件源對象上發生操作時,它將會調用事件監聽器的一個方法,并在調用該方法時傳遞事件對象過去

事件監聽器實現類,通常是由開發人員編寫,開發人員通過事件對象拿到事件源,從而對事件源上的操作進行處理

舉個例子

這里我為了方便,直接使用jdk,EventListener 監聽器,感興趣的可以去研究下源碼,非常簡單。

監聽器接口

public interface EventListener extends java.util.EventListener {

//事件處理

public void handleEvent(EventObject event);

}

事件對象

public class EventObject extends java.util.EventObject{

private static final long serialVersionUID = 1L;

public EventObject(Object source){

super(source);

}

public void doEvent(){

System.out.println("通知一個事件源 source :"+ this.getSource());

}

}

事件源

事件源是事件對象的入口,包含監聽器的注冊、撤銷、通知

public class EventSource {

//監聽器列表,監聽器的注冊則加入此列表

private Vector<EventListener> ListenerList = new Vector<EventListener>();

//注冊監聽器

public void addListener(EventListener eventListener){

ListenerList.add(eventListener);

}

//撤銷注冊

public void removeListener(EventListener eventListener){

ListenerList.remove(eventListener);

}

//接受外部事件

public void notifyListenerEvents(EventObject event){

for(EventListener eventListener:ListenerList){

eventListener.handleEvent(event);

}

}

}

測試執行

public static void main(String[] args) {

EventSource eventSource = new EventSource();

}

控制臺顯示:

通知一個事件

很赞哦!(25295)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:四川达州达县

工作室:小组

Email:[email protected]