摘要:總結一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發布訂閱模式,卻不僅僅只有發布者和訂閱者兩個角色,還有第三個角色經紀人存在。參考鏈接觀察者模式發布訂閱模式
做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關于設計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設計模式在從頭學習一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...至于其他的,慢慢來。廢話不多說,還是進入正題吧!
從定義上看:觀察者模式 是當對象(不知道什么是對象的,面壁思過切...)間存在一對多關系時,則使用 觀察者模式 ,比如,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式 屬于 行為型模式 (不會還要讓我講一下設計模式的分類吧?我不要在這里講...)。
其實,我所理解的 觀察者模式 ,就是觀察和被觀察對象之間的關系,好比說,在拍賣的時候,拍賣師觀察最高標價,然后通知給其他競價者競價。在這里面,拍賣師是觀察者,而那些競價者,是被觀察者,文字不太好理解是吧,那我們畫個圖看一下:
從圖中我們可以看到,拍賣師觀察競價者1的標價,拿到了最高標價,然后在通知其他競價者,這就是一個簡單的觀察者模式圖示,仔細看一下這個圖,我們會發現,最基礎的觀察者模式中,涉及以下幾種角色:
被觀察者:競價者們;
觀察者:拍賣師;
具體的被觀察者:競價者們的出價動作;
具體的觀察者:拍賣師觀察競價者的動作;
按照上述的四種角色,我們來用代碼還原一下觀察者模式的實現:
/** * 抽象被觀察者(競價者們) **/ public abstract class Subject { // 用來保存注冊的觀察者對象 private Listlist = new ArrayList<>(); // 注冊觀察者對象 public void attach(Observer observer) { list.add(observer); System.out.println("Attached an observer"); } // 通知所有注冊的觀察者對象 public void nodifyObservers(int price) { for (Observer observer : list) { observer.update(price); } } } /** * 抽象觀察者角色類(拍賣師) **/ public interface Observer { public void update(int price); } /** * 具體的被觀察者實現類(競價者們的動作) **/ public class BidderSubject extends Subject { private int price; public void change(int price) { this.price = price; System.out.println("競價者說:" + price + "元"); // 競價者們說出價格,通知觀察者 this.nodifyObservers(price); } } /** * 具體的觀察者實現類(拍賣師的動作) **/ public class AuctionObserver implements Observer { // 觀察者的動作 private int observerAction; @Override public void update(int price) { // 更新觀察者的動作,使其與被觀察者(競價者們出價)的消息保持一致 observerAction = price; System.out.println("好,某某出價為:" + observerAction + "元,還有沒有更高的?"); } } /** * 客戶端執行類 **/ public class Main { public static void main(String[] args) { // 創建被觀察者(競價者)主題對象 BidderSubject bidderSubject = new BidderSubject(); // 創建觀察者(拍賣師)對象 Observer observer = new AuctionObserver(); // 將觀察者(拍賣師)對象登記到被觀察對象(競價者們)上 bidderSubject.attach(observer); // 改變被觀察者(競價者們)的出價 bidderSubject.change(20); } }
最后我們看一下執行結果:
其實在 Java 中,還是比較容易理解抽象這個概念,但是在 JavaScript 語言中,因為沒有 多態 ,所以在實現上,沒有 java 這么明顯的看出觀察者和被觀察者的關系,但是我們還是可以實現這個觀察者模式,在這里,博主使用的是 es6 的一個新特性:Proxy 和 Reflect ,這兩個 api 的具體使用這里就不在贅述了,有興趣的可以看看 阮一峰 老師的 ES6入門學習 ,具體的還是讓我們直接看代碼吧:
// 添加觀察者的方法 const observers = new Set(); const observe = fn => observers.add(fn); // 設置Proxy的set方法 function set(target, key, value, receiver) { console.log(`競價者說:${value}元`); const result = Reflect.set(target, key, value, receiver); observers.forEach(observer => observer()); return result; } // 創建Proxy代理,實現被觀察者對象的抽象 const subject = obj => new Proxy(obj, {set}); // 被觀察者(競價者們)對象,默認數值 const bidderSubject = subject({ price: 0, }); // 觀察者(拍賣師)對象 function auctionObserver() { console.log(`拍賣師說:有人出價${bidderSubject.price}元,還有沒有要出價的?`); } // 添加觀察者 observe(auctionObserver); // 競價者出價 bidderSubject.price = 20;
執行結果與上面 Java 是一致的,還是上圖吧,證明一下博主是木有說謊的:
這就是簡單的觀察者實現方式,在 javascript 我們有輔助的 api 就是 Proxy 和 Reflect,翻譯成中文是 代理 和 反射,別小看這他倆哈,作用其實很大的,具體的就不在這里說了,以后有機會給大家補一篇具體的使用說明。
其實我們在學習 觀察者模式 的時候,還會蹦出來一個詞語叫 發布-訂閱模式,大多數人都會說,這倆可以劃等號,但是他們真的可以劃等號么?答案就是(PS:博主的表情是壞笑):不,他們不是一個東西,(戲精出現:what?why?)。
網上有個說法是:觀察者模式 是為了實現松耦合,我們從 Java 的代碼看到,實現 觀察者模式 用的是面向接口編程,整套實現的流程是:change() 方法所在的實例對象,就是 被觀察者 (Subject類)只需要維護一套 觀察者(Observer) 的集合,這些 Observer 實現相同的接口,Subject只需要知道,通知 Observer 時,需要調用哪個統一方法(例子中的 change()方法)就好了。
而 發布-訂閱模式 呢,發布者(被觀察者),并不會直接通知訂閱者(觀察者),換句話說,發布者和訂閱者,彼此互不相識,或許這里該有同學問了:他們互不相識?那他們之間該如何交流呢?答案是:通過第三者,也就是在消息隊列里面,我們常說的 經紀人-Broker。
> 發布者只需要告訴 Broker,我要發的消息是,price是20,
> 訂閱者只需要告訴 Broker,我要訂閱price是20的消息。
于是,當 Broker 收到 發布者 發過來消息,并且price是20時,就會把消息推送給訂閱了price是20的 訂閱者。當然也有可能是 訂閱者 自己過來拉取,看具體實現。
也就是說,發布-訂閱模式里, 發布者 和 訂閱者,不是松耦合,而是完全解耦的。
總結一下:
從表面上看:
觀察者模式里,只有兩個角色 —— 觀察者+被觀察者
而發布訂閱模式,卻不僅僅只有發布者和訂閱者兩個角色,還有第三個角色-經紀人Broker存在。
往更深層次講:
觀察者和被觀察者,是松耦合的關系;
發布者和訂閱者,則完全不存在耦合。
其實我們在學習設計模式的時候,很多模式的實現,都是有一定依據的,首先離不開的就是面向對象三大特性,其次是面向對象七大原則,而設計模式則是對面向對象更具體的實現,我們學習這些模式的時候,還是要多去寫代碼實踐一下,這些能有效的幫助我們優化代碼。
參考鏈接:
觀察者模式 vs 發布訂閱模式
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74976.html
摘要:關鍵概念理解觀察者設計模式中主要區分兩個概念觀察者指觀察者對象,也就是消息的訂閱者被觀察者指要觀察的目標對象,也就是消息的發布者。 原文首發于微信公眾號:jzman-blog,歡迎關注交流! 最近補一下設計模式相關的知識,關于觀察者設計模式主要從以下幾個方面來學習,具體如下: 什么是觀察者設計模式 關鍵概念理解 通知觀察者的方式 觀察者模式的實現 觀察者模式的優缺點 使用場景 下面...
摘要:觀察者模式與發布訂閱的區別在模式中,知道,同時還保留了的記錄。發布者訂閱者在大多情況下是異步方式使用消息隊列。圖片源于網絡侵權必刪如果以結構來分辨模式,發布訂閱模式相比觀察者模式多了一個中間件訂閱器,所以發布訂閱模式是不同于觀察者模式的。 學習了一段時間設計模式,當學到觀察者模式和發布訂閱模式的時候遇到了很大的問題,這兩個模式有點類似,有點傻傻分不清楚,博客起因如此,開始對觀察者和發布...
摘要:總結一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發布訂閱模式,卻不僅僅只有發布者和訂閱者兩個角色,還有第三個角色經紀人存在。參考鏈接觀察者模式發布訂閱模式 做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關于設計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設計模式在從頭學習一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...
摘要:或許以前認為訂閱發布模式是觀察者模式的一種別稱,但是發展至今,概念已經有了不少區別。參考文章訂閱發布模式和觀察者模式真的不一樣 首選我們需要先了解兩者的定義和實現的方式,才能更好的區分兩者的不同點。 或許以前認為訂閱發布模式是觀察者模式的一種別稱,但是發展至今,概念已經有了不少區別。 訂閱發布模式 在軟件架構中,發布-訂閱是一種消息范式,消息的發送者(稱為發布者)不會將消息直接發送給特...
摘要:觀察者模式又稱發布訂閱模式,模型視圖模式,源監聽器模式模式或者從屬者模式。第一方法被調用之后會設置一個內部標記變量,代表被觀察者對象的狀態發生了變化。代碼地址觀察者模式代碼自己實現的觀察者模式利用提供的有關觀察者模式的 概念 定義了對象之間的一對多依賴,當一個對象狀態改變時,它的所有依賴者都會收到通知并自動更新。觀察者模式又稱發布(Publish/Subscribe)訂閱模式,模型視圖...
閱讀 3718·2021-10-12 10:11
閱讀 1984·2019-08-30 15:53
閱讀 1592·2019-08-30 13:15
閱讀 2307·2019-08-30 11:25
閱讀 1803·2019-08-29 11:24
閱讀 1652·2019-08-26 13:53
閱讀 3526·2019-08-26 13:22
閱讀 1766·2019-08-26 10:24