亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript 設計模式(六):觀察者模式與發(fā)布訂閱模式

bingo / 2728人閱讀

摘要:觀察者模式維護單一事件對應多個依賴該事件的對象關系發(fā)布訂閱維護多個事件主題及依賴各事件主題的對象之間的關系觀察者模式是目標對象直接觸發(fā)通知全部通知,觀察對象被迫接收通知。

觀察者模式(Observer)
觀察者模式:定義了對象間一種一對多的依賴關系,當目標對象 Subject 的狀態(tài)發(fā)生改變時,所有依賴它的對象 Observer 都會得到通知。

簡單點:女神有男朋友了,朋友圈曬個圖,甜蜜宣言 “老娘成功脫單,希望你們歡喜”。各位潛藏備胎紛紛失戀,只能安慰自己你不是唯一一個。

模式特征

一個目標者對象 Subject,擁有方法:添加 / 刪除 / 通知 Observer;

多個觀察者對象 Observer,擁有方法:接收 Subject 狀態(tài)變更通知并處理;

目標對象 Subject 狀態(tài)變更時,通知所有 Observer

Subject 添加一系列 Observer, Subject 負責維護與這些 Observer 之間的聯(lián)系,“你對我有興趣,我更新就會通知你”。

代碼實現(xiàn)
// 目標者類
class Subject {
  constructor() {
    this.observers = [];  // 觀察者列表
  }
  // 添加
  add(observer) {
    this.observers.push(observer);
  }
  // 刪除
  remove(observer) {
    let idx = this.observers.findIndex(item => item === observer);
    idx > -1 && this.observers.splice(idx, 1);
  }
  // 通知
  notify() {
    for (let observer of this.observers) {
      observer.update();
    }
  }
}

// 觀察者類
class Observer {
  constructor(name) {
    this.name = name;
  }
  // 目標對象更新時觸發(fā)的回調
  update() {
    console.log(`目標者通知我更新了,我是:${this.name}`);
  }
}

// 實例化目標者
let subject = new Subject();

// 實例化兩個觀察者
let obs1 = new Observer("前端開發(fā)者");
let obs2 = new Observer("后端開發(fā)者");

// 向目標者添加觀察者
subject.add(obs1);
subject.add(obs2);

// 目標者通知更新
subject.notify();  
// 輸出:
// 目標者通知我更新了,我是前端開發(fā)者
// 目標者通知我更新了,我是后端開發(fā)者
優(yōu)勢

目標者與觀察者,功能耦合度降低,專注自身功能邏輯;

觀察者被動接收更新,時間上解耦,實時接收目標者更新狀態(tài)。

不完美

觀察者模式雖然實現(xiàn)了對象間依賴關系的低耦合,但卻不能對事件通知進行細分管控,如 “篩選通知”,“指定主題事件通知” 。

比如上面的例子,僅通知 “前端開發(fā)者” ?觀察者對象如何只接收自己需要的更新通知?上例中,兩個觀察者接收目標者狀態(tài)變更通知后,都執(zhí)行了 update(),并無區(qū)分。

“00后都在追求個性的時代,我能不能有點不一樣?”,這就引出我們的下一個模式。進階版的觀察者模式?!鞍l(fā)布訂閱模式”,部分文章對兩者是否一樣都存在爭議。

僅代表個人觀點:兩種模式很類似,但是還是略有不同,就是多了個第三者,因 JavaScript 非正規(guī)面向對象語言,且函數(shù)回調編程的特點,使得 “發(fā)布訂閱模式” 在 JavaScript 中代碼實現(xiàn)可等同為 “觀察模式”。

發(fā)布訂閱模式(Publisher && Subscriber)
發(fā)布訂閱模式:基于一個事件(主題)通道,希望接收通知的對象 Subscriber 通過自定義事件訂閱主題,被激活事件的對象 Publisher 通過發(fā)布主題事件的方式通知各個訂閱該主題的 Subscriber 對象。

發(fā)布訂閱模式與觀察者模式的不同,“第三者” (事件中心)出現(xiàn)。目標對象并不直接通知觀察者,而是通過事件中心來派發(fā)通知。

代碼實現(xiàn)
// 事件中心
let pubSub = {
  list: {},
  subscribe: function (key, fn) {   // 訂閱
    if (!this.list[key]) {
      this.list[key] = [];
    }
    this.list[key].push(fn);
  },
  publish: function(key, ...arg) {  // 發(fā)布
    for(let fn of this.list[key]) {
      fn.call(this, ...arg);
    }
  },
  unSubscribe: function (key, fn) {     // 取消訂閱
    let fnList = this.list[key];
    if (!fnList) return false;

    if (!fn) {
      // 不傳入指定取消的訂閱方法,則清空所有key下的訂閱
      fnList && (fnList.length = 0);
    } else {
      fnList.forEach((item, index) => {
        if (item === fn) {
          fnList.splice(index, 1);
        }
      })
    }
  }
}

// 訂閱
pubSub.subscribe("onwork", time => {
  console.log(`上班了:${time}`);
})
pubSub.subscribe("offwork", time => {
  console.log(`下班了:${time}`);
})
pubSub.subscribe("launch", time => {
  console.log(`吃飯了:${time}`);
})

// 發(fā)布
pubSub.publish("offwork", "18:00:00"); 
pubSub.publish("launch", "12:00:00");

// 取消訂閱
pubSub.unSubscribe("onwork");

發(fā)布訂閱模式中,訂閱者各自實現(xiàn)不同的邏輯,且只接收自己對應的事件通知。實現(xiàn)你想要的 “不一樣”。

DOM 事件監(jiān)聽也是 “發(fā)布訂閱模式” 的應用:

let loginBtn = document.getElementById("#loginBtn");

// 監(jiān)聽回調函數(shù)(指定事件)
function notifyClick() {
    console.log("我被點擊了");
}

// 添加事件監(jiān)聽
loginBtn.addEventListener("click", notifyClick);
// 觸發(fā)點擊, 事件中心派發(fā)指定事件
loginBtn.click();             

// 取消事件監(jiān)聽
loginBtn.removeEventListener("click", notifyClick);

發(fā)布訂閱的通知順序:

先訂閱后發(fā)布時才通知(常規(guī))

訂閱后可獲取過往以后的發(fā)布通知 (QQ離線消息,上線后獲取之前的信息)

流行庫的應用

jQuery 的 ontrigger,$.callback();

Vue 的雙向數(shù)據綁定;

Vue 的父子組件通信 $on/$emit

jQuery 的 $.Callback()

jQuery 的 $.Callback() 更像是觀察者模式的應用,不能更細粒度管控。

function notifyHim(value) {
 console.log("He say " + value);
}

function notifyHer(value) {
 console.log("She say " + value);
}

$cb = $.Callbacks();    // 聲明一個回調容器:訂閱列表 

$cb.add(notifyHim);     // 向回調列表添加回調:訂閱
$cb.add(notifyHer);     // 向回調列表添加回調:訂閱

$cb.fire("help");       // 調用所有回調: 發(fā)布
Vue 的雙向數(shù)據綁定

利用 Object.defineProperty() 對數(shù)據進行劫持,設置一個監(jiān)聽器 Observer,用來監(jiān)聽數(shù)據對象的屬性,如果屬性上發(fā)生變化了,交由 Dep 通知訂閱者 Watcher 去更新數(shù)據,最后指令解析器 Compile 解析對應的指令,進而會執(zhí)行對應的更新函數(shù),從而更新視圖,實現(xiàn)了雙向綁定。

Observer (數(shù)據劫持)

Dep (發(fā)布訂閱)

Watcher (數(shù)據監(jiān)聽)

Compile (模版編譯)

關于 Vue 雙向數(shù)據綁定原理,可自行參考其它文章,或推薦本篇 《 vue雙向數(shù)據綁定原理》。

Vue源碼傳送門

Vue 的父子組件通信

Vue 中,父組件通過 props 向子組件傳遞數(shù)據(自上而下的單向數(shù)據流)。父子組件之間的通信,通過自定義事件即 $on , $emit 來實現(xiàn)(子組件 $emit,父組件 $on)。

原理其實就是 $emit 發(fā)布更新通知,而 $on 訂閱接收通知。Vue 中還實現(xiàn)了 $once(一次監(jiān)聽),$off(取消訂閱)。

// 訂閱
vm.$on("test", function (msg) {
    console.log(msg)
})

// 發(fā)布
vm.$emit("test", "hi")

Vue源碼傳送門

Vue文檔傳送門

優(yōu)勢

對象間功能解耦,弱化對象間的引用關系;

更細粒度地管控,分發(fā)指定訂閱主題通知

不完美

對間間解耦后,代碼閱讀不夠直觀,不易維護;

額外對象創(chuàng)建,消耗時間和內存(很多設計模式的通?。?/p> 觀察者模式 VS 發(fā)布訂閱模式

類似點

都是定義一個一對多的依賴關系,有關狀態(tài)發(fā)生變更時執(zhí)行相應的通知。

區(qū)別點

發(fā)布訂閱模式更靈活,是進階版的觀察者模式,指定對應分發(fā)。

觀察者模式維護單一事件對應多個依賴該事件的對象關系;

發(fā)布訂閱維護多個事件(主題)及依賴各事件(主題)的對象之間的關系;

觀察者模式是目標對象直接觸發(fā)通知(全部通知),觀察對象被迫接收通知。發(fā)布訂閱模式多了個中間層(事件中心),由其去管理通知廣播(只通知訂閱對應事件的對象);

觀察者模式對象間依賴關系較強,發(fā)布訂閱模式中對象之間實現(xiàn)真正的解耦。

對象屬性數(shù)據攔截方式:

Object.defineProperty() 屬性描述符;

ES6 Class set ;

ES6 Proxy 代理;

參考文章:

談談觀察者模式和發(fā)布訂閱模式

原生JavaScript實現(xiàn)觀察者模式

觀察者模式 vs 發(fā)布訂閱模式

vue雙向數(shù)據綁定原理

本文首發(fā)Github,期待Star!
https://github.com/ZengLingYong/blog

作者:以樂之名
本文原創(chuàng),有不當?shù)牡胤綒g迎指出。轉載請指明出處。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/105523.html

相關文章

  • JavaScript設計模式發(fā)布-訂閱模式察者模式)-Part1

    摘要:設計模式與開發(fā)實踐讀書筆記。發(fā)布訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關系。附設計模式之發(fā)布訂閱模式觀察者模式數(shù)據結構和算法系列棧隊列優(yōu)先隊列循環(huán)隊列設計模式系列設計模式之策略模式 《JavaScript設計模式與開發(fā)實踐》讀書筆記。 發(fā)布-訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關系。當一個對象的狀態(tài)發(fā)生改變時,所有依賴它的對象都將得到通知。 例...

    muzhuyu 評論0 收藏0
  • JavaScript 發(fā)布-訂閱模式

    摘要:發(fā)布訂閱模式訂閱者把自己想訂閱的事件注冊到調度中心,當發(fā)布者發(fā)布該事件到調度中心,也就是該事件觸發(fā)時,由調度中心統(tǒng)一調度訂閱者注冊到調度中心的處理代碼。 發(fā)布-訂閱模式,看似陌生,其實不然。工作中經常會用到,例如 Node.js EventEmitter 中的 on 和 emit 方法;Vue 中的 $on 和 $emit 方法。他們都使用了發(fā)布-訂閱模式,讓開發(fā)變得更加高效方便。 一...

    13651657101 評論0 收藏0
  • JavaScript設計模式發(fā)布-訂閱模式察者模式)-Part2

    摘要:設計模式與開發(fā)實踐讀書筆記??创宋恼虑?,建議先看設計模式之發(fā)布訂閱模式觀察者模式在中,已經介紹了什么是發(fā)布訂閱模式,同時,也實現(xiàn)了發(fā)布訂閱模式。 《JavaScript設計模式與開發(fā)實踐》讀書筆記。 看此文章前,建議先看JavaScript設計模式之發(fā)布-訂閱模式(觀察者模式)-Part1 在Part1中,已經介紹了什么是發(fā)布-訂閱模式,同時,也實現(xiàn)了發(fā)布-訂閱模式。但是,就Part1...

    Charlie_Jade 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<