天天看點

javascript設計模式_JavaScript設計模式之觀察者模式

前言

最近在學習

RxJS

,由于

RxJS

中有兩個重要的概念

Observable

Observer

中使用了觀察者模式,是以就對該模式學習一遍,順便對一些常用的設計模式進行了一些了解。雖然平時很少用設計模式,但是設計模式的思想卻出現在我們使用的各種架構中,甚至ES6的API中,時刻與我們相伴。學習好JavaScript真的是前路漫漫,還需努力!

本次分享主要包括:

  • 觀察者模式簡介
  • 觀察者模式的使用場景
  • 觀察者模式的實作
  • 觀察者模式的優缺點

簡介

觀察者模式又叫作釋出—訂閱模式,是我們最常用的設計模式之一(其實這兩種模式還是存在一定的差別)。它定義了對象間的一種一對多的依賴關系。當一個對象的狀态發生改變時,所有依賴它的對象都将得到通知和更新。觀察者模式提供了一個訂閱模型,其中對象訂閱事件并在事件發生時得到通知。這種模式是事件驅動的程式設計基石,它有利于良好的面向對象的設計。

如果上面的描述不是很容易了解,我們舉個生活中的例子:拿買房來講,如果你想買房,但是你看好的樓盤還沒有開盤,是以你就将你的電話留給售樓小姐,一旦樓盤推出就讓她打電話給你。主動權在售樓方,而你隻需要提供一個聯系方式,不需要你每天都打電話就能知道樓盤出來了沒。樓盤相當于被觀察者,你相當于觀察者。或者說你是訂閱者,訂閱了樓盤是否推出這一事件。

學習了

RxJS

後對觀察者模式有了更為深刻的了解,觀察者本質上就是将資料的産生與資料處理的邏輯相分離,被觀察者負責資料的産生,觀察者負責處理資料,即産生的資料流與處理資料的邏輯分離開來。

使用場景

[1] DOM事件

實際上,隻要我們曾經在DOM節點上綁定過事件函數,那我們就使用過觀察者模式,因為JS和DOM之間就是實作了一種觀察者模式。

document.body.addEventListener("click", function() {    alert("Hello World")},false )document.body.click() //模拟使用者點選
           

上面代碼中,需要監聽使用者點選document.body的動作,但是我們沒有辦法預知使用者将在什麼時候點選。是以我們訂閱了document.body的click事件,當body節點被點選時,body節點便會向訂閱者釋出"Hello World"消息。

[2] Vue中watch

javascript設計模式_JavaScript設計模式之觀察者模式

watch方法就是監聽的data中firstName和lastName,當資料發生變化,就會通知到watch中的兩個方法,執行相應的改變。

[3] NodeJs中http請求

javascript設計模式_JavaScript設計模式之觀察者模式

http讀取資料流,由于是分片讀取,我們無法預知資料流什麼時候讀取完成,是以我們訂閱了end事件,當資料流讀取完成後,就會釋出讀取完成的消息,進而進行下一步生成頁面的操作。

當然了還有很多例子,比如ES6中的Promise、Vue和React中的生命周期函數等,就不一一列舉了。

實作

觀察者模式是對象間一種一對多的關系,有釋出和訂閱兩種模式,在實作之前我們先畫一個類圖:

javascript設計模式_JavaScript設計模式之觀察者模式

其中Observer是觀察者,Subject是被觀察到對象。觀察者中有被觀察者的引用。被觀察者中有存放了觀察者的數組,并有添加觀察者和通知觀察者的兩個方法。

具體實作如下:

// 被觀察者class Subject {    constructor() {        this.state = 0;        this.observers = [];    }    getState() {        return this.state;    }    setState(state) {        this.state = state;        this.notifyAllObservers();    }    notifyAllObservers() {        this.observers.forEach(observer => {            observer.update()        })    }    attach(observer) {        this.observers.push(observer)    }}// 觀察者class Observer {    constructor(name, subject) {        this.name = name;        this.subject = subject;        this.subject.attach(this);    }    update() {        console.log(`${this.name} update, state ${this.subject.getState()}`)    }}// 測試代碼let s = new Subject();let o1 = new Observer('o1', s);let o2 = new Observer('o2', s);let o3 = new Observer('o3', s);s.setState(1);
           

本例中實作的是監聽被觀察者

state

的變化,被觀察者執行了

setState

的方法時,所有的觀察者就行了各自的

update

方法。

優點與不足

觀察者模式的優點非常明顯:一是時間上的解耦,二是對象之間的解耦。既可用于異步程式設計中,也可以用幫助我們完成更松耦合的代碼編寫。但它仍然有所不足:

  • 建立訂閱者本身要消耗一定的時間和記憶體
  • 當訂閱一個消息時,也許此消息并沒有發生,但這個訂閱者會始終存在記憶體中。
  • 觀察者模式弱化了對象之間的聯系,這本是好事情,但如果過度使用,對象與對象之間的聯系也會被隐藏的很深,會導緻項目的難以跟蹤維護和了解。

小結

本次分享介紹了觀察者模式,舉例說明了觀察者模式在我們身邊的應用。通過建立

Observer

Subject

兩個類實作了觀察者模式,作為一個簡單的參考友善以後在我們的業務場景中使用。最後介紹了觀察者模式的優缺點,在選擇使用觀察者模式的時候作為一個提醒。本次分享如果有誤,還請大家批評指正!

繼續閱讀