前言
最近在學習
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
watch方法就是監聽的data中firstName和lastName,當資料發生變化,就會通知到watch中的兩個方法,執行相應的改變。
[3] NodeJs中http請求
http讀取資料流,由于是分片讀取,我們無法預知資料流什麼時候讀取完成,是以我們訂閱了end事件,當資料流讀取完成後,就會釋出讀取完成的消息,進而進行下一步生成頁面的操作。
當然了還有很多例子,比如ES6中的Promise、Vue和React中的生命周期函數等,就不一一列舉了。
實作
觀察者模式是對象間一種一對多的關系,有釋出和訂閱兩種模式,在實作之前我們先畫一個類圖:
其中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
兩個類實作了觀察者模式,作為一個簡單的參考友善以後在我們的業務場景中使用。最後介紹了觀察者模式的優缺點,在選擇使用觀察者模式的時候作為一個提醒。本次分享如果有誤,還請大家批評指正!