有時候面試的時候可能會被問到:面試
觀察者模式和發佈訂閱模式的區別?設計模式
沒有區別吧?測試
好像有區別吧?this
咱們首先來看一下「觀察者模式」和「發佈訂閱模式」spa
理解設計模式在設計之初的是爲了解決什麼問題就能很好的在寫代碼中運用不一樣的設計模式。prototype
所謂的觀察者模式,其實爲了實現鬆耦合(loosely coupled),也就是爲了解耦。設計
當數據有變化有更新的時候,某個方法被調用,這時候就能夠更新其餘地方須要用到這個數據的地方。code
舉個例子:server
以氣象站爲例,每當氣象站測試數據有更新的時候,changed()方法都會被調用,因而咱們在changed()方法中,更新氣象儀器上的數據,好比溫度、氣壓等等。中間件
這樣寫沒有毛病,可是,若是咱們之後再changed()方法調用的時候,更新更多的信息,好比說溼度,這個時候咱們須要去修改changed()方法的代碼,這個就是緊耦合的壞處。
那怎麼解決這個緊耦合的問題呢?
觀察者模式中,changed()方法所在的實例對象,就是被觀察者(subject),只須要維護一套觀察者(observer)的集合,這些observer實現相同的接口,subject只須要知道:通知觀察者(observer)時,須要調用哪個統一方法就行。
咱們再來看一下簡單的例子
function Subject(){ this.observerData = []; } Subject.prototype = { add: function(observer) { this.observerData.push(observer); }, remove:function(observer) { var observerData = this.observerData; for(let i=0,length=observerData.length;i<length;i++){ if(observerData[i] === observer){ observerData.splice(i,1) } } }, notify: function() { var observerData = this.observerData; for(let i=0,length=observerData.length;i<length;i++){ observerData[i].update(); } } } function Observer(name){ this.name = name; } Observer.prototype = { update: function() { console.log('hello,' + this.name); } } var sub = new Subject(); var obj1 = new Observer('saucxs'); var obj2 = new Observer('songEagle'); sub.add(obj1); sub.add(obj2); sub.notify();
這時候輸出的是
hello,saucxs
hello,songEagle
上述代碼中,咱們建立了Subject對象和兩個Observer對象,當前狀態發生變動的時候則經過Subject對象的notify方法通知兩個Observer隊形,這兩個Observer對象經過update方法進行更新。
其實以爲發佈訂閱模式裏的Publisher,就是觀察者模式的Subject,而Subscriber就是Observer。Publisher變化的時候,就會主動去通知Subscriber。
其實並非這樣的。
在發佈訂閱模式裏,發佈者並不會直接通知訂閱者,換句話說,發佈者和訂閱者,彼此互補相識。
那他們之間如何進行通訊的?是經過第三者,就是在消息隊列中,咱們常說的經紀人Broker。
發佈者只須要告訴Broker,我要發消息。topic是「saucxs」
訂閱者只須要告訴Broker,我要訂閱topic是「saucxs」
因而,當Broker接收到發佈者發來的消息,而且topic是saucxs的時候,就會把消息推送到訂閱了topic的saucxs的訂閱者,也多是訂閱者本身過來拉取,具體看代碼實現。
也就是說,發佈訂閱模式中,發佈者和訂閱者,不是鬆耦合,是徹底的解耦的。
放一張很簡單的圖,對比一下兩個模式的區別:
表面上看:
一、觀察者模式中,兩個角色:觀察者和被觀察者
二、發佈訂閱模式中,三個角色:發佈者,訂閱者,經紀人
深層次的看:
一、觀察者模式:觀察者和被觀察者,是鬆耦合的關係
二、發佈訂閱模式:發佈和訂閱者是徹底不存在耦合的
從使用層面上看:
一、觀察者模式:多用於單個應用內部,維護的是單一事件對應多個依賴的
event -> [obj1,obj2,obj3,....]
二、發佈訂閱模式:多用於跨應用的模式,好比咱們說的消息的中間件,維護的是多個事件以及依賴的
event1 -> [obj1,obj2,...]event2 -> [obj1,obj3,...]