日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

别再面向 for 循环编程了,JDK 自带的观察者模式就很香!

發(fā)布時(shí)間:2025/3/16 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 别再面向 for 循环编程了,JDK 自带的观察者模式就很香! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大家好,你還在面向 for 循環(huán)編程嗎?

還有誰不會用觀察者模式嗎?

本篇帶來《觀察者模式》理論及實(shí)戰(zhàn)~

???

什么是觀察者模式?

觀察者模式(Observer Pattern)定義了對象間的一種一對多的依賴關(guān)系,這樣只要一個(gè)對象的狀態(tài)發(fā)生改變,其依賴的所有相關(guān)對象都會得到通知并自動(dòng)更新。

在觀察者模式中,發(fā)生改變的對象叫做觀察目標(biāo),而被通知更新的對象稱為觀察者,一個(gè)觀察目標(biāo)對應(yīng)多個(gè)觀察者,觀察者一般是一個(gè)列表集合,可以根據(jù)需要?jiǎng)討B(tài)增加和刪除,易于擴(kuò)展。

使用觀察者模式的優(yōu)點(diǎn)在于觀察目標(biāo)和觀察者之間是抽象松耦合關(guān)系,降低了兩者之間的耦合關(guān)系。

?

發(fā)布-訂閱模式

觀察者模式很多地方也叫發(fā)布-訂閱模式(Publish/Subscribe),其實(shí)也可以這么理解,不過兩者之間還是略有不同。

觀察者模式中的觀察者是直接綁定觀察目標(biāo),觀察目標(biāo)要維護(hù)一套觀察者列表,兩者是有一個(gè)基于接口的組合依賴關(guān)系的,所以說觀察者模式雖然是松耦合的,但并不是完全解耦的。

發(fā)布-訂閱模式中的發(fā)布者和訂閱者兩者并沒有任何聯(lián)系,發(fā)布者通過中間方發(fā)布一個(gè)主題(Topic),訂閱者通過中間方(調(diào)度中心)訂閱一個(gè)主題(Topic),發(fā)布者狀態(tài)的變更也并不會直接通知訂閱者,而要通過中間方進(jìn)行通知,或者訂閱者自行從中間方拉取,所以說發(fā)布-訂閱模式是完全解耦的。

一圖搞懂它們的關(guān)系:

觀察者模式和訂閱發(fā)布模式的區(qū)別

從圖片看兩者是有差別的,統(tǒng)一都叫觀察者模式,也沒毛病。

?

觀察者模式輪子

因觀察者模式應(yīng)用比較廣泛,所以 JDK 工具包從 1.0 版本里面自帶了觀察者模式模板套裝,我們根據(jù)其模板很方便就能實(shí)現(xiàn)觀察者模式,不需要再重復(fù)造輪子了。

觀察者目標(biāo)類:

java.util.Observable

里面兩個(gè)最重要的變量:

  • changed:觀察目標(biāo)狀態(tài)是否變更,默認(rèn)為:false;

  • obs:觀察者列表(observers),一個(gè)線程安全的列表集合:Vector,默認(rèn)為空集合;

里面的重要的方法都是和觀察目標(biāo)狀態(tài)和觀察者相關(guān)的,一看就清楚,這里就不介紹了。

觀察者接口:

java.util.Observable

public?interface?Observer?{/***?This?method?is?called?whenever?the?observed?object?is?changed.?An*?application?calls?an?<tt>Observable</tt>?object's*?<code>notifyObservers</code>?method?to?have?all?the?object's*?observers?notified?of?the?change.**?@param???o?????the?observable?object.*?@param???arg???an?argument?passed?to?the?<code>notifyObservers</code>*?????????????????method.*/void?update(Observable?o,?Object?arg); }

觀察者接口只有一個(gè) update 方法,用來通知觀察者自己更新。

?

觀察者模式實(shí)戰(zhàn)

OK,知道了 JDK 自帶了這兩個(gè)東東,現(xiàn)在就來實(shí)現(xiàn)一個(gè)簡單的觀察者模式的應(yīng)用場景,模擬公眾號文章推送,觀察目標(biāo)是棧長我,觀察者是你們大家,我在公眾號棧推一篇文章,你們都能接收到更新通知并能閱讀。

新增觀察目標(biāo)類:

import?lombok.Getter;import?java.util.Observable;/***?觀察目標(biāo):棧長*/ @Getter public?class?JavaStackObservable?extends?Observable?{private?String?article;/***?發(fā)表文章*?@param?article*/public?void?publish(String?article){//?發(fā)表文章this.article?=?article;//?改變狀態(tài)this.setChanged();//?通知所有觀察者this.notifyObservers();}}

觀察目標(biāo)的邏輯是先發(fā)表文章,再改變觀察目標(biāo)的狀態(tài),再通知所有觀察者。

我們來重點(diǎn)看 notifyObservers 方法的源碼:

先獲取同步鎖,判斷狀態(tài)是否更新,如已更新則清空觀察目標(biāo)狀態(tài),然后再使用 for 循環(huán)遍歷所有觀察者,一一調(diào)用觀察者的更新方法通知觀察者更新。

新增觀察者類:

import?lombok.NonNull; import?lombok.RequiredArgsConstructor;import?java.util.Observable; import?java.util.Observer;/***?觀察者:讀者粉絲*/ @RequiredArgsConstructor public?class?ReaderObserver?implements?Observer?{@NonNullprivate?String?name;private?String?article;@Overridepublic?void?update(Observable?o,?Object?arg)?{//?更新文章updateArticle(o);}private?void?updateArticle(Observable?o)?{JavaStackObservable?javaStackObservable?=?(JavaStackObservable)?o;this.article?=?javaStackObservable.getArticle();System.out.printf("我是讀者:%s,文章已更新為:%s\n",?this.name,?this.article);}}

觀察者的邏輯是獲取到觀察者目標(biāo)實(shí)例對象,然后再用觀察目標(biāo)對象的文章信息更新為自己的文章信息,最后輸出某某某的文章已更新。

觀察者只要實(shí)現(xiàn) Observer 這個(gè)接口的 update 方法即可,用于觀察目標(biāo)進(jìn)行調(diào)用通知。

觀察目標(biāo)和觀察者類結(jié)構(gòu)圖如下:

新增測試類:

/***?觀察者:讀者粉絲*/ public?class?ObserverTest?{public?static?void?main(String[]?args)?{//?創(chuàng)建一個(gè)觀察目標(biāo)JavaStackObservable?javaStackObservable?=?new?JavaStackObservable();//?添加觀察者javaStackObservable.addObserver(new?ReaderObserver("小明"));javaStackObservable.addObserver(new?ReaderObserver("小張"));javaStackObservable.addObserver(new?ReaderObserver("小愛"));//?發(fā)表文章javaStackObservable.publish("什么是觀察者模式?");}}

觀察目標(biāo)、觀察者的創(chuàng)建并沒有先后順序要求,重點(diǎn)是發(fā)表文章通知觀察者之前,觀察目標(biāo)要添加觀察者列表這一步不能少。

輸出結(jié)果:

通過這個(gè)簡單的文章推送實(shí)踐,大家應(yīng)該對觀察者模式有一個(gè)基本的認(rèn)知了,在實(shí)際工作當(dāng)中也可以有很多場景拿去用,就一對多的依賴關(guān)系都可以考慮使用觀察者模式。

?

總結(jié)

不容易啊,陸陸續(xù)續(xù)又肝了大半天,你學(xué)會觀察者模式了嗎?

觀察者模式的優(yōu)點(diǎn)是為了給觀察目標(biāo)和觀察者解耦,而缺點(diǎn)也很明顯,從上面的例子也可以看出,如果觀察者對象太多的話,有可能會造成內(nèi)存泄露。

另外,從性能上面考慮,所有觀察者的更新都是在一個(gè)循環(huán)中排隊(duì)進(jìn)行的,所以觀察者的更新操作可以考慮做成線程異步(或者可以使用線程池)的方式,以提升整體效率。

有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

歡迎大家關(guān)注Java之道公眾號

好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的别再面向 for 循环编程了,JDK 自带的观察者模式就很香!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。