摘要:觀察者模式介紹觀察者模式又稱發(fā)布訂閱模式,它定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象發(fā)生改變的時(shí)候,所依賴它的對(duì)象都能得到通知。關(guān)于內(nèi)部的觀察者模式可以參數(shù)這篇文檔??偨Y(jié)總之,觀察者模式在中的使用是非常廣泛的。
javascript觀察者模式 介紹
觀察者模式又稱發(fā)布-訂閱模式,它定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象發(fā)生改變的時(shí)候,所依賴它的對(duì)象都能得到通知。例如:我們訂閱了一個(gè)欄目,當(dāng)欄目有新文章的時(shí)候,它會(huì)自動(dòng)通知所有訂閱它的人。
特點(diǎn)發(fā)布 & 訂閱
一對(duì)多
優(yōu)點(diǎn)低耦合,觀察者和觀察目標(biāo)都是抽象出來,容易擴(kuò)展和重用
觸發(fā)(通訊)機(jī)制,由觀察目標(biāo)通知所有觀察它的人
缺點(diǎn)一個(gè)觀察目標(biāo)下可能存在很多的觀察者,那么當(dāng)觀察目標(biāo)需要通知所有觀察者的時(shí)候會(huì)花很多時(shí)間
觀察者和觀察目標(biāo)之間如果存在依賴的話,可能會(huì)發(fā)生循環(huán)調(diào)用,進(jìn)入死循環(huán)導(dǎo)致系統(tǒng)崩潰
觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道觀察目標(biāo)是如何發(fā)生變化,僅僅知道觀察目標(biāo)發(fā)生了變化
觀察目標(biāo)可能將一些無用的更新發(fā)送出去
簡(jiǎn)單例子例子:A,B,C三個(gè)人都關(guān)注了某一個(gè)電臺(tái),當(dāng)電臺(tái)發(fā)布新內(nèi)容的時(shí)候通知A,B,C三個(gè)人。
構(gòu)思:具體的構(gòu)思中,我們可以知道電臺(tái)作為發(fā)布者,它有了新的內(nèi)容,需要向ABC這三個(gè)訂閱者推送他的最新的消息。那么我們就可以知道電臺(tái)這個(gè)發(fā)布者需要包含新的更新內(nèi)容以及有哪些訂閱者訂閱了它。
代碼實(shí)現(xiàn):
簡(jiǎn)單的代碼實(shí)現(xiàn):
class Radio { constructor() { this.state = 0; this.observers = []; } setState(state) { this.state = state; this.notifyingObservers(); } addObserver(observer) { this.observers.push(observer); } notifyingObservers() { const state = this.state; this.observers.forEach(observer => { observer.update(state); }); } } class People { constructor(name) { this.name = name; } update(content) { console.log(`我是${this.name},我接受到更新了,更新內(nèi)容:${content}`); } } // 創(chuàng)建訂閱者 const peopleA = new People("小A"); const peopleB = new People("小B"); const peopleC = new People("小C"); // 添加發(fā)布者 const radio = new Radio(); // 訂閱 radio.addObserver(peopleA); radio.addObserver(peopleB); radio.addObserver(peopleC); // 發(fā)布者發(fā)布 radio.setState("十月份最熱歌單發(fā)布了"); radio.setState("十一月份最新原創(chuàng)歌單發(fā)布了");
解讀:
抽象了一個(gè)發(fā)布者(Radio),它有更新內(nèi)容(setState)、添加訂閱者(addObserver)、以及觸發(fā)所有訂閱者(notifyingObservers);
抽象了一個(gè)訂閱者(People),他有自己的個(gè)人信息(如:name),以及接受到通知后所需要執(zhí)行的動(dòng)作(updata);
當(dāng)我們每次更新消息的時(shí)候出發(fā)notifyingObservers方法,將所有的observers的update都觸發(fā)了
當(dāng)然,實(shí)際上,我們上的每一個(gè)訂閱者都有這個(gè)update,當(dāng)這個(gè)update不滿足功能需求的時(shí)候,我們同樣可以將實(shí)例出來的訂閱者多帶帶設(shè)置update; 如:
peopleA.update = function(content) { // 新代碼 }
以上就是一個(gè)簡(jiǎn)單的觀察者模式的例子
場(chǎng)景延伸網(wǎng)頁(yè)頁(yè)面事件
代碼案例:
解讀:可以理解成函數(shù)訂閱了$("#btn")的click事件,當(dāng)$("#btn")的click被我們點(diǎn)擊觸發(fā),函數(shù)收到觸發(fā)信息,并自執(zhí)行。 那么這個(gè)函數(shù)就是觀察者(訂閱者),$("#btn")的click事件就是觀察目標(biāo)(發(fā)布者)。
Promise
代碼案例:
function loadImage(url) { return new Promise(function(resolve, reject) { let image = document.createElement("img"); image.onload = function () { resolve(image); } image.onerror = function () { reject("圖片加載失敗"); } image.src = url; }); } const src = "http://imgsrc.baidu.com/image/c0%3Dpixel_huitu%2C0%2C0%2C294%2C40/sign=ad13ee4af0f2b211f0238d0ea3f80054/2e2eb9389b504fc26849383ceedde71190ef6df1.jpg" const img = loadImage(src); img.then(function (img) { console.log("width", img.width); return img }).then(function (img) { console.log("height", img.height); });
解讀:promise的resolve是then的執(zhí)行者,當(dāng)promise的狀態(tài)發(fā)生改變后(resolve的時(shí)候狀態(tài)從”未完成“變?yōu)椤背晒Α?,一一執(zhí)行then下的方法,那么這些then可以說是promise的觀察者,當(dāng)這個(gè)promise被resolve的時(shí)候,所有的觀察得到了通知。
關(guān)于promise內(nèi)部的觀察者模式可以參數(shù)https://github.com/xieranmaya/blog/issues/3這篇文檔。
promise.then會(huì)把內(nèi)部的函數(shù)添加到一個(gè)callback的數(shù)組內(nèi),等異步執(zhí)行完成之后在進(jìn)行一次調(diào)用該函數(shù)。每一個(gè).then會(huì)返回一個(gè)新的promise。
js的事件觸發(fā)器(自定義事件)
代碼案例:
class EventEmitter() { constructor() { this.events = {}; } // 訂閱事件 on(type, listener) { if (!this.events) { this.events = Object.create(null); } if (this.events[type]) { this.events[type].push(listener) } else { this.events[type] = [listener]; } } // 觸發(fā)執(zhí)行 emit(type, ...args) { if (this.events[type]) { this.events[type].forEach(fn => fn.call(this, ...args)); } } // 解綁 off(type, listener) { id (this.events[type]) { this.events[type] = this.events[type].filter(fn => { return fn !== listener; }); } } } const myEmitter = new EventEmitter(); myEmitter.on("log", function() {console.log("111111")}); myEmitter.emit("log");
解讀:這個(gè)就和第一個(gè)案例有點(diǎn)相似,我們?cè)趈q中見過這樣的頁(yè)面事件寫法:
$("id").on("click", function() { // 事件代碼 });
這個(gè)就是一種事件觸發(fā)器,在nodejs里面大量采用了事件觸發(fā)器的方法。詳情可以去看nodejs里面的EventEmitter方法,就可以大體理解他的機(jī)制了。
同理,我們也可以明白react里面的生命周期等mvvm框架,里面大量采用了觀察者模式。它們都是定義了一個(gè)個(gè)鉤子,等狀態(tài)達(dá)到的時(shí)候我就觸發(fā)相對(duì)應(yīng)的鉤子,執(zhí)行相對(duì)應(yīng)的代碼。
總之,觀察者模式在javascript中的使用是非常廣泛的。其低耦合的特點(diǎn)方便在多人開發(fā)的復(fù)雜項(xiàng)目中,能提高效率,使代碼的維護(hù)性大大提升。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99005.html
摘要:作用默認(rèn)的,直接在當(dāng)前線程運(yùn)行總是開啟一個(gè)新線程用于密集型任務(wù),如異步阻塞操作,這個(gè)調(diào)度器的線程池會(huì)根據(jù)需要增長(zhǎng)對(duì)于普通的計(jì)算任務(wù),請(qǐng)使用默認(rèn)是一個(gè),很像一個(gè)有線程緩存的新線程調(diào)度器計(jì)算所使用的。這個(gè)使用的固定的線程池,大小為核數(shù)。 轉(zhuǎn)載請(qǐng)注明出處:https://zhuanlan.zhihu.com/p/20687307 RxJava系列1(簡(jiǎn)介) RxJava系列2(基本概念及使...
摘要:我們今天也來做一個(gè)萬能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:我們今天也來做一個(gè)萬能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:是的縮寫,起源于,是一個(gè)基于可觀測(cè)數(shù)據(jù)流結(jié)合觀察者模式和迭代器模式的一種異步編程的應(yīng)用庫(kù)。是基于觀察者模式和迭代器模式以函數(shù)式編程思維來實(shí)現(xiàn)的。學(xué)習(xí)之前我們需要先了解觀察者模式和迭代器模式,還要對(duì)流的概念有所認(rèn)識(shí)。 RxJS 是 Reactive Extensions for JavaScript 的縮寫,起源于 Reactive Extensions,是一個(gè)基于可觀測(cè)數(shù)據(jù)流 Stre...
閱讀 1981·2019-08-30 15:54
閱讀 3608·2019-08-29 13:07
閱讀 3132·2019-08-29 12:39
閱讀 1799·2019-08-26 12:13
閱讀 1555·2019-08-23 18:31
閱讀 2167·2019-08-23 18:05
閱讀 1856·2019-08-23 18:00
閱讀 1052·2019-08-23 17:15