前端技術日新月異,我們忙着學習各種新技能,光是學會使用,就已筋疲力盡。
你或許也有這種感覺,這也是我曾經的狀态。但你所不知道的是,我們使用的元件架構,它們基本是使用設計模式實作的。運用設計模式,對代碼開發和維護效率,有極大提升。想了解設計模式更多資訊,可以點我頭像看往期文章。
今天我們談到的,是觀察者模式,一種你經常使用,卻不自知的設計模式。Vue架構的響應式原理,watch監聽對象,bus消息總線等,都是運用了觀察者模式實作的。設計模式的運用離我們非常貼近,隻是沒有發現。
下面我分三方面,和你分享我的見解。
1 觀察者模式的定義
2 使用場景
3 新手也能實作的觀察者模式
觀察者模式的定義
百度百科的定義是這樣的
觀察者模式(有時又被稱為模型(Model)-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目标物件管理所有相依于它的觀察者物件,并且在它本身的狀态改變時主動發出通知。這通常通過呼叫各觀察者所提供的方法來實作。此種模式通常被用來實作事件處理系統。
通俗的說,就是一個對象A,被多個對象依賴。多個對象訂閱A的變化,當A發生變化時,能夠釋出變化,通知到依賴方的模式。
類似微信公衆号,你訂閱了“web前端快車道”的公衆号,後續每次公衆号有更新,會推送給訂閱的所有使用者。
這就是觀察者模式,也稱為釋出-訂閱模式,本質就是訂閱對象,當對象發生變化,就會釋出消息通知到訂閱者。
使用場景
觀察者模式,定義了一種一對多的對象依賴關系。當對象發生變化,所有的依賴都能得到通知。
從定義就能看出,使用觀察者模式,前提是存在一對多的依賴。如果隻是單一對象的依賴,就沒必要使用觀察者模式。
在項目開發中,有以下兩種常見運用場景
a 異步程式設計的回調。
異步程式設計是指這部分邏輯是異步執行的,比如發送請求到背景,或者動态加載一個元件,這些都需要一段時間後,才會完成。而完成後,通過事件通知到依賴此回調的對象。這樣就避免了,傳統方式給異步邏輯傳遞回調函數,通過回調告知結果。隻需要廣播一個完成事件,需要得知結果的對象,訂閱了這個事件,就能得知變化。把釋出者和訂閱者解耦,後續有新的依賴者,自行訂閱對象即可,無需釋出者修改代碼。這也展現了設計模式的基本原則,不變和可變分離的原則。
b 對象屬性資料發生變化
在Vue等架構出現前,一個對象資料發生變化,如果想通知依賴的對象,往往需要直接調用依賴對象的方法進行通知。依賴對象多的時候,需要在變化時,調用各種不同的依賴對象,釋出和訂閱方耦合嚴重。
通過觀察者模式,在發生變化時,發送通知事件,訂閱者自主訂閱接收,就可以優雅的實作對象監聽。
Vue架構中,我們通過watch,監聽data資料或Vuex狀态,本質就是上面講的監聽對象狀态的觀察者模式,是watch幫我們完成了事件的訂閱接收。
新手也能實作的觀察者模式
實作觀察者模式,需要三個核心能力
a 訂閱者存儲集合
b 釋出事件
c 訂閱事件
原生的JavaScript可以快速實作,下面為你分享一個簡單的實作邏輯
var Event = (function(){
var clientList = {} // 存儲訂閱者
var listen
var trigger
// key為訂閱事件名,fn為訂閱對象回調
listen = function( key, fn ){
if ( ! clientList[ key ] ){
clientList[ key ] = []
}
clientList[ key ].push( fn )
}
trigger = function(){
var key = Array.prototype.shift.call( arguments ),
fns = clientList[ key ]
if ( ! fns || fns.length === 0 ){
return false
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments )
}
}
return {
listen: listen,
trigger: trigger
}
})();
// 訂閱消息
Event.listen( 'eventA', function( price ){
console.log( ’價格= ' + price )
})
// 釋出消息
Event.trigger( 'eventA', 2000000 )
代碼實作比較簡單,就不過多贅述了。
希望大家能持續學習,通過實踐總結,真正把設計模式的思想,凝練為自己的東西。
祝願我們都能寫出優雅的代碼,不斷提升技術能力!