觀察者模式還是非常常用的,常見于基于zookeeper進行分布式系統之間的協調工作,比如分布式鎖的注冊以及監聽是否釋放。還有就是兩個系統之間如果做了異步的處理,那么如果A系統發送異步請求給了B系統,但是要得到B系統的一個狀態改變的消息,可以采用觀察者模式。
創新互聯建站主營長安網站建設的網絡公司,主營網站建設方案,app軟件開發,長安h5小程序定制開發搭建,長安網站營銷推廣歡迎長安等地區企業咨詢
使用場景
在Zookeeper中的監聽回調機制,以及分布式鎖,都是使用了觀察者模式。
基于zookeeper去做分布式鎖
(1)系統A嘗試獲取zookeeper上的一個鎖,獲取到了
(2)系統B嘗試獲取zookeeper上的一個鎖,被系統A給鎖了,沒有獲取到鎖,此時系統B在zookeeper上可以注冊一個監聽器(觀察者)
(3)系統A一旦將鎖給釋放了,zookeeper感受到鎖被釋放了,就會立即通知系統B注冊的那個監聽器
(4)系統B就立即被通知到了,系統A釋放了鎖,系統B可以重新嘗試在zookeeper上加鎖
電商系統里,也有這種場景,如果兩個系統之間走了異步請求,那么可以基于上面那種觀察者模式現在一個進程內實現監聽,以后拆分微服務分布式架構了,可以改成基于zookeeper來做分布式協調。
系統A發送了一條消息到內存隊列,系統B獲取了消息開始執行操作
但是系統A需要知道系統B的一個執行的結果如何,
此時系統A需要注冊一個觀察者到系統B上去,系統B執行完了之后,將執行的結果,反過來通知給系統
我們就可以基于觀察者模式去做。
官方解釋:
觀察者模式(有時又被稱為發布-訂閱Subscribe模式、模型-視圖View模式、源-收聽者Listener模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理所有相依于它的觀察者物件,并且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實作事件處理系統。
個人理解:
觀察者模式是一種思想,不需要人為的去關注觀察者和被觀察者之間是怎樣聯系的,實現了解耦,只需要對象去注冊被觀察者(Observerable)與觀察者(Observer),然后被觀察者去添加一個或者多個觀察者,當被觀察者發生變動就會立即通知所有的觀察者,下面讓我們來看看是怎樣實現這個功能的。
被觀察者首先通過addObserver(Observer o)來添加一個觀察者,底層代碼中會把這個對象o放進一個vector集合中,當然也可以添加多個觀察者,當觀察者發生變動的時候就會觸發
setChanged();
notifyObservers();
這兩個方法,然后底層代碼中就回去遍歷裝有觀察者的那個vector,然后
for (int i = arrLocal.length-1; i=0; i--)
((Observer)arrLocal[i]).update(this, arg);
調用update方法通知每一個觀察者,這樣觀察者對象中就可以拿到被觀察者的相關對象和信息
當我們想訂一份報紙,我們先去郵局找到報紙的編號后填寫訂閱單并繳費。當報社有新報紙發出時,郵局會將我們訂閱的報紙發給我們。
為了簡單我們去掉郵局環節簡化成:報社有新報紙后馬上通知用戶,這就是觀察者。
定義對象間的一對多關系,當一個對象的狀態發生變化時,所依賴于它的對象都得到通知并主動更新。 在觀察者模式中,多個訂閱者成為觀察者(Observer),被觀察的對象成為目標(Subject)。觀察者的UML模型如下:
先定義Subject并寫一個ConcreteSubject繼承Subject:
再定義一個接口Observer,并寫一個ConcreteObserver實現Observer接口:
最后看看主函數方法:
打印出來的結果:
在實現觀察者模式的時候,一定要注意觸發通知的時機。一般情況下是在完成了狀態改變之后觸發,因為通知會傳遞數據,比如在 setSubjectState 時先通知觀測者就會發生 錯誤 。
在觀察者模式的實現上,有推模式和拉模式兩種方式:
當前上面的實現使用的就是拉模型。通過 (ConcreteSubject)subject 得到具體對象,獲得信息。
當然Java本身就有觀察者模式的部分實現,分別是 java.util.Observable java.util.Observable 。
下面看一個使用Java自帶觀察者模式的例子:
新的目標直接繼承Java中定義的Observerable:
新的觀察者也直接實現Observer接口:
主函數和前面的相似:
打印出結果:
使用Java自帶的觀察者模式需要注意以下幾個問題:
觀察者(Observer)模式又名發布-訂閱(Publish/Subscribe)模式。GOF給觀察者模式如下定義:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。
在這里先講一下面向對象設計的一個重要原則——單一職責原則。因此系統的每個對象應該將重點放在問題域中的離散抽象上。因此理想的情況下,一個對象只做一件事情。這樣在開發中也就帶來了諸多的好處:提供了重用性和維護性,也是進行重構的良好的基礎。
因此幾乎所有的設計模式都是基于這個基本的設計原則來的。觀察者模式的起源我覺得應該是在GUI和業務數據的處理上,因為現在絕大多數講解觀察者模式的例子都是這一題材。但是觀察者模式的應用決不僅限于此一方面。
下面我們就來看看觀察者模式的組成部分。
1)抽象目標角色(Subject):目標角色知道它的觀察者,可以有任意多個觀察者觀察同一個目標。并且提供注冊和刪除觀察者對象的接口。目標角色往往由抽象類或者接口來實現。
2)抽象觀察者角色(Observer):為那些在目標發生改變時需要獲得通知的對象定義一個更新接口。抽象觀察者角色主要由抽象類或者接口來實現。
3)具體目標角色(ConcreteSubject):將有關狀態存入各個ConcreteObserver對象。當它的狀態發生改變時,向它的各個觀察者發出通知。
4)具體觀察者角色(ConcreteObserver):存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer的更新接口以使自身狀態與目標的狀態保持一致。在本角色內也可以維護一個指向ConcreteSubject對象的引用。
定義 :對象間的一種一對多的依賴關系,使得當每一個對象改變狀態,則所有依賴于他的對象都會得到通知,并自動更新。
交互對象之間松耦合
1)觀察者定義了對象之間一對多的關系
2)被觀察者用一個共同的接口來更新觀察者
3)觀察者和被觀察者用松耦合方式結合,被觀察者不知道觀察者的細節,只知道觀察者實現了觀察者接口
優點:
1)觀察者與被觀察者抽象耦合,容易擴展;
2)建立了一套觸發機制。
缺點:
1)循環依賴會導致系統崩潰;
2)觀察者太多會浪費時間。
1)定義對象之間的一對多依賴關系而不使對象緊密耦合。
2)確保當一個對象改變狀態時,自動更新開放數量的從屬對象。
3)一個對象應該可以通知開放式數量的其他對象。
觀察者模式 vs 發布-訂閱模式
觀察者模式(Observer)
如何使用 Java8 實現觀察者模式?(上)
如何使用 Java8 實現觀察者模式?(下)
spring 事件為bean 與 bean之間傳遞消息。一個bean處理完了希望其余一個接著處理.這時我們就需要其余的一個bean監聽當前bean所發送的事件.
spring事件使用步驟如下:
1.先自定義事件:你的事件需要繼承 ApplicationEvent
2.定義事件監聽器: 需要實現 ApplicationListener
3.使用容器對事件進行發布
最后有一個思考 :ApplicationEvent事件執行部分和起一個TaskExecutor去執行 有啥區別嗎?反正都是異步。
可以這樣實現;
還可以這樣實現;
我的思考:ApplicationEvent是觀察者設計模式,這種設計模式使得主題和觀察者之間的耦合度降低,松耦合是面向對象設計中很重要的一個原則,最終也是使用@Async來實現異步。而TaskExecutor則是啟動一個線程池任務異步執行任務,兩者效果一樣,但原理不同。
通過我的思考,又帶來一個疑問:那觀察者模式是不是就是我們MQ中的發布訂閱模式呢?只不過觀察者模式是進程內的,而MQ是跨進程的?就這唯一的區別嗎?
經過一些資料的查閱:大多數地方觀察者模式 約等于 發布訂閱模式,但是觀察者模式是由具體目標調度的,而發布/訂閱模式是統一由調度中心調的,所以觀察者模式的訂閱者與發布者之間是存在依賴的,而發布/訂閱模式則不會。
所以說觀察者模式是小米加步槍,發布訂閱模式是95式自動步槍,是它的進化版!
網頁標題:go語言實現觀察者模式 go 觀察者模式
網站網址:http://m.kartarina.com/article12/dodsggc.html
成都網站建設公司_創新互聯,為您提供、品牌網站設計、關鍵詞優化、網站設計公司、手機網站建設、網頁設計公司
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯