观察者模式案例的简单分析
觀察者模式
簡介
觀察者模式也叫發布-訂閱模式,其定義如下:定義對象間一種一對多的依賴關系,使得當該對象狀態改變時,所有依賴于它的對象都會得到通知,并被自動更新。
觀察者模式的通知方式可以通過直接調用等同步方式實現(如函數調用,HTTP接口調用等),也可以通過消息隊列異步調用(同步調用指被觀察者發布消息后,必須等所有觀察者響應結束后才可以進行接下來的操作;異步調用指被觀察者發布消息后,即可進行接下來的操作)。
簡單來說,就是在軟件設計中維護一個依賴列表,當任何狀態發生改變自動通知他們。借用一個在博客看到的例子,觀察者模式就像報紙和雜志的訂閱:向某家報社訂閱報紙,只要報社有新的的報紙出版,就會給你送來,只要你是他們的客戶,你就會一直收到新的報紙。當你不想再看報紙的時候,可以取消訂閱,他們就不再送新的報紙過來。
只要報社還一直在運營,就會一直有人(或單位)向他們訂閱報紙或取消訂閱報紙。
特點
對于一個大型復雜的系統,觀察者模式可以很好的解決類間消息交換的問題。總結來說,觀察者模式有以下優點:
- 觀察者和被觀察者之間是抽象耦合的;
- 可以把許多負責單一職責的模塊進行觸發,也可以很方便的實現廣播。
觀察者模式的優點有時候也會是缺點,他可能會帶來整體系統效率的浪費,同時如果被觀察者之間有依賴關系的話,其邏輯關系的梳理需要費一些心思。
案例分析
我在github上看到了一個同學做的例子,覺得還不錯:一個模塊加載器的簡單實現
這個案例實現了一個簡單的模塊加載器,其中就用到了觀察者模式。接下來我們分析一下其中用到的觀察者模式。
對于Watcher這個構造函數,task是一個待執行的callback,uris是這個異步callback所依賴的模塊(地址),dep是一個訂閱器。$len是依賴模塊的數組長度。如果一個模塊加載好了,那么通知這個Watcher,這個Watcher的$len變量就減一。對于一個Watcher,我們不用關心當前到底是哪個模塊加載好了,反正只能是所有依賴模塊加載好,這個task才能被執行。所以當$len為零的時候,表面依賴全部加載好,那么這個Wathcer就執行這個task。
function Watcher(task, uris, dep, Module){this.$task = task;this.$uris = uris;this.dep = dep;this.$Module = Module;this.modArr = [];this.$len = this.$uris.length; }Watcher每執行一次update,this.$len--。當為零的時候,執行this.run()方法。this.run()中,如果task是一個函數,那么執行執行。因為在define函數中,如果define里面沒有依賴,就會將其callback直接放入Watcher。如果有依賴,則會先創建一個task對象,將當前define腳本的src存入task,以便觸發該dep的notify方法。
Watcher.prototype = {update: function () {this.$len--;if (this.$len <= 0) {this.run();}},run: function () {let mod = this.$Module.module,task = this.$task;this.$uris.forEach(uri => {this.modArr.push(mod[uri].obj);});//this.$Module.module[this.dep.depName].obj =if (typeof task == 'function') {task.apply(null, this.modArr);return}let src = task.currentSrc;mod[src].obj = task.callback.apply(null, this.modArr);mod[src].dep.notify();this.dep.removeSub(this);return} };Dep是一個訂閱器,用一個訂閱器來存放一個模塊,不管define有多深,模塊a依賴于模塊b,模塊b依賴于模塊c。當模塊c加載好后(約定模塊c是不依賴于任何其他模塊的),模塊c的訂閱器dep觸發notify方法,subs里面的Watcher的update方法。
function Dep(depName){this.id = uid++;this.subs = [];this.depName = depName; }Dep.prototype = {/*** 添加訂閱, 將watcher添加進數組subs* @param {Object} task new watcher()*/addSubs: function(task){this.subs.push(task);},/*** 刪除訂閱, 將watcher從數組subs中刪除* @param {Object} task new watcher()*/removeSub: function(task){let index = this.subs.indexOf(task);(index != -1) && this.subs.splice(index, 1);},/*** 當該模塊加載好的時候, 通知所有依賴它的task*/notify: function(){this.subs.forEach(task => {task.update();});} };以上就實現了一個簡單的模塊加載器。一個對象的改變狀態,則所有依賴于它的對象都會得到通知更新。在這個例子中Watcher跟Dep之間是關聯關系,是抽象耦合的,它們之間形成一條觸發鏈,依次對每一個Dep中的對象進行處理。這樣就很好的解決了對象之間的通信問題。
轉載于:https://www.cnblogs.com/luuu/p/9842960.html
總結
以上是生活随笔為你收集整理的观察者模式案例的简单分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android本地文件点击视频播放器vi
- 下一篇: 数仓:维度建模